code:
/*	$OpenBSD: opendev.c,v 1.9 2006/03/09 23:06:19 miod Exp $	*/
/*	$NetBSD: openfirm.c,v 1.1 1996/09/30 16:34:52 ws Exp $	*/

/*
 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
 * Copyright (C) 1995, 1996 TooLs GmbH.
 * All rights reserved.
 *
 * 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 TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
 */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/stdarg.h>
#include <machine/psl.h>

#include <dev/ofw/openfirm.h>

extern void ofw_stack(void);
extern void ofbcopy(const void *, void *, size_t);

int
OF_instance_to_package(int ihandle)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int ihandle;
		int phandle;
	} args = {
		"instance-to-package",
		1,
		1,
	};

	ofw_stack();
	args.ihandle = ihandle;
	if (openfirmware(&args) == -1)
		return -1;
	return args.phandle;
}

int
OF_package_to_path(int phandle, char *buf, int buflen)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int phandle;
		char *buf;
		int buflen;
		int length;
	} args = {
		"package-to-path",
		3,
		1,
	};

	ofw_stack();
	if (buflen > PAGE_SIZE)
		return -1;
	args.phandle = phandle;
	args.buf = OF_buf;
	args.buflen = buflen;
	if (openfirmware(&args) < 0)
		return -1;
	if (args.length > 0)
		ofbcopy(OF_buf, buf, args.length);
	return args.length;
}

int
OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...)
{
	va_list ap;
	static struct {
		char *name;
		int nargs;
		int nreturns;
		char *method;
		int ihandle;
		int args_n_results[12];
	} args = {
		"call-method",
		2,
		1,
	};
	int *ip, n;

	if (nargs > 6)
		return -1;
	args.nargs = nargs + 2;
	args.nreturns = nreturns + 1;
	args.method = method;
	args.ihandle = ihandle;
	va_start(ap, nreturns);
	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
		*--ip = va_arg(ap, int);
	ofw_stack();
	if (openfirmware(&args) == -1) {
		va_end(ap);
		return -1;
	}
	if (args.args_n_results[nargs]) {
		va_end(ap);
		return args.args_n_results[nargs];
	}
	for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
		*va_arg(ap, int *) = *--ip;
	va_end(ap);
	return 0;
}
int
OF_call_method_1(char *method, int ihandle, int nargs, ...)
{
	va_list ap;
	static struct {
		char *name;
		int nargs;
		int nreturns;
		char *method;
		int ihandle;
		int args_n_results[8];
	} args = {
		"call-method",
		2,
		2,
	};
	int *ip, n;

	if (nargs > 6)
		return -1;
	args.nargs = nargs + 2;
	args.method = method;
	args.ihandle = ihandle;
	va_start(ap, nargs);
	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
		*--ip = va_arg(ap, int);
	va_end(ap);
	ofw_stack();
	if (openfirmware(&args) == -1)
		return -1;
	if (args.args_n_results[nargs])
		return -1;
	return args.args_n_results[nargs + 1];
}

int
OF_open(char *dname)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		char *dname;
		int handle;
	} args = {
		"open",
		1,
		1,
	};
	int l;

	ofw_stack();
	if ((l = strlen(dname)) >= PAGE_SIZE)
		return -1;
	ofbcopy(dname, OF_buf, l + 1);
	args.dname = OF_buf;
	if (openfirmware(&args) == -1)
		return -1;
	return args.handle;
}

void
OF_close(int handle)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int handle;
	} args = {
		"close",
		1,
		0,
	};

	ofw_stack();
	args.handle = handle;
	openfirmware(&args);
}

/*
 * This assumes that character devices don't read in multiples of PAGE_SIZE.
 */
int
OF_read(int handle, void *addr, int len)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int ihandle;
		void *addr;
		int len;
		int actual;
	} args = {
		"read",
		3,
		1,
	};
	int l, act = 0;

	ofw_stack();
	args.ihandle = handle;
	args.addr = OF_buf;
	for (; len > 0; len -= l, addr += l) {
		l = min(PAGE_SIZE, len);
		args.len = l;
		if (openfirmware(&args) == -1)
			return -1;
		if (args.actual > 0) {
			ofbcopy(OF_buf, addr, args.actual);
			act += args.actual;
		}
		if (args.actual < l) {
			if (act)
				return act;
			else
				return args.actual;
		}
	}
	return act;
}

int
OF_write(int handle, void *addr, int len)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int ihandle;
		void *addr;
		int len;
		int actual;
	} args = {
		"write",
		3,
		1,
	};
	int l, act = 0;

	ofw_stack();
	args.ihandle = handle;
	args.addr = OF_buf;
	for (; len > 0; len -= l, addr += l) {
		l = min(PAGE_SIZE, len);
		ofbcopy(addr, OF_buf, l);
		args.len = l;
		if (openfirmware(&args) == -1)
			return -1;
		l = args.actual;
		act += l;
	}
	return act;
}

int
OF_seek(int handle, u_quad_t pos)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int handle;
		int poshi;
		int poslo;
		int status;
	} args = {
		"seek",
		3,
		1,
	};

	ofw_stack();
	args.handle = handle;
	args.poshi = (int)(pos >> 32);
	args.poslo = (int)pos;
	if (openfirmware(&args) == -1)
		return -1;
	return args.status;
}


code:
/*	$OpenBSD: openfirm.c,v 1.11 2015/03/31 10:36:52 mpi Exp $	*/
/*	$NetBSD: openfirm.c,v 1.1 1996/09/30 16:34:52 ws Exp $	*/

/*
 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
 * Copyright (C) 1995, 1996 TooLs GmbH.
 * All rights reserved.
 *
 * 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 TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
 */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/stdarg.h>
#include <machine/psl.h>

#include <dev/ofw/openfirm.h>

extern void ofw_stack(void);
extern void ofbcopy(const void *, void *, size_t);

int
OF_peer(int phandle)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int phandle;
		int sibling;
	} args = {
		"peer",
		1,
		1,
	};

	ofw_stack();
	args.phandle = phandle;
	if (openfirmware(&args) == -1)
		return 0;
	return args.sibling;
}

int
OF_child(int phandle)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int phandle;
		int child;
	} args = {
		"child",
		1,
		1,
	};

	ofw_stack();
	args.phandle = phandle;
	if (openfirmware(&args) == -1)
		return 0;
	return args.child;
}

int
OF_parent(int phandle)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int phandle;
		int parent;
	} args = {
		"parent",
		1,
		1,
	};

	ofw_stack();
	args.phandle = phandle;
	if (openfirmware(&args) == -1)
		return 0;
	return args.parent;
}

int
OF_getproplen(int handle, char *prop)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int phandle;
		char *prop;
		int size;
	} args = {
		"getproplen",
		2,
		1,
	};

	ofw_stack();
	args.phandle = handle;
	args.prop = prop;
	if (openfirmware(&args) == -1)
		return -1;
	return args.size;
}

int
OF_getprop(int handle, char *prop, void *buf, int buflen)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int phandle;
		char *prop;
		void *buf;
		int buflen;
		int size;
	} args = {
		"getprop",
		4,
		1,
	};

	ofw_stack();
	if (buflen > NBPG)
		return -1;
	args.phandle = handle;
	args.prop = prop;
	args.buf = OF_buf;
	args.buflen = buflen;
	if (openfirmware(&args) == -1)
		return -1;
	if (args.size > 0)
		ofbcopy(OF_buf, buf, args.size);
	return args.size;
}

int
OF_setprop(int handle, char *prop, const void *buf, int buflen)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		int phandle;
		char *prop;
		void *buf;
		int buflen;
		int size;
	} args = {
		"setprop",
		4,
		1,
	};

	ofw_stack();
	if (buflen > NBPG)
		return -1;
	args.phandle = handle;
	args.prop = prop;
	ofbcopy(buf, OF_buf, buflen);
	args.buf = OF_buf;
	args.buflen = buflen;
	if (openfirmware(&args) == -1)
		return -1;
	return args.size;
}

int
OF_nextprop(int handle, char *prop, void *nextprop)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int phandle;
		const char *prop;
		char *buf;
		int flag;
	} args = {
		"nextprop",
		3,
		1,
	};

	ofw_stack();
	args.phandle = handle;
	args.prop = prop;
	args.buf = OF_buf;
	if (openfirmware(&args) == -1)
		return -1;
	strlcpy(nextprop, OF_buf, 32);
	return args.flag;
}

int
OF_interpret(char *cmd, int nreturns, ...)
{
	va_list ap;
	int i;
	static struct {
		char *name;
		int nargs;
		int nreturns;
		char *cmd;
		int status;
		int results[8];
	} args = {
		"interpret",
		1,
		2,
	};

	ofw_stack();
	if (nreturns > 8)
		return -1;
	if ((i = strlen(cmd)) >= NBPG)
		return -1;
	ofbcopy(cmd, OF_buf, i + 1);
	args.cmd = OF_buf;
	args.nargs = 1;
	args.nreturns = nreturns + 1;
	if (openfirmware(&args) == -1)
		return -1;
	va_start(ap, nreturns);
	for (i = 0; i < nreturns; i++)
		*va_arg(ap, int *) = args.results[i];
	va_end(ap);
	return args.status;
}

int
OF_finddevice(char *name)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
		char *device;
		int phandle;
	} args = {
		"finddevice",
		1,
		1,
	};

	ofw_stack();
	args.device = name;
	if (openfirmware(&args) == -1)
		return -1;
	return args.phandle;
}
static void OF_rboot(char *bootspec);

static void
OF_rboot(char *bootspec)
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
	} args = {
		"reset-all",
		0,
		0,
	};
	int l;

	if ((l = strlen(bootspec)) >= NBPG)
		panic("OF_boot");
	ofw_stack();
	openfirmware(&args);
	/* will attempt exit in OF_boot */
}

void
OF_boot(char *bootspec)
{
	OF_rboot(bootspec);
	printf ("OF_boot returned!");		/* just in case */
	OF_exit();
	while(1);
}

void
OF_exit()
{
	static struct {
		char *name;
		int nargs;
		int nreturns;
	} args = {
		"exit",
		0,
		0,
	};

	ofw_stack();
	openfirmware(&args);
	panic ("OF_exit returned!");		/* just in case */
	while (1);
}

void
OF_quiesce(void)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
	} args = {
		"quiesce",
		0,
		0,
	};

	ofw_stack();
	openfirmware(&args);
}

/* XXX What is the reason to have this instead of bcopy/memcpy? */
void
ofbcopy(const void *src, void *dst, size_t len)
{
        const char *sp = src;
        char *dp = dst;

        if (src == dst)
                return;

        while (len-- > 0)
                *dp++ = *sp++;
}

int
OF_getnodebyname(int start, const char *name)
{
	char nname[32];
	int len;
	int node = 0;
	int next;

	if (start == 0)
		start = OF_peer(0);

	for (node = start; node; node = next) {
		len = OF_getprop(node, "name", nname, sizeof(nname));
		nname[len] = 0;
		if (strcmp(nname, name) == 0) {
			return node;
		}
		if ((next = OF_child(node)) != 0)
			continue;
		while (node) {
			if ((next = OF_peer(node)) != 0)
				break;
			node = OF_parent(node);
		}
	}
	return node;
}

license: unknown


code:
/*	$OpenBSD: openprom.c,v 1.3 2014/07/12 18:44:42 tedu Exp $	*/
/*	$NetBSD: openprom.c,v 1.4 2002/01/10 06:21:53 briggs Exp $ */

/*
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * 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, Lawrence Berkeley Laboratory.
 *
 * 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. 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.
 *
 *	@(#)openprom.c	8.1 (Berkeley) 6/11/93
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/conf.h>
#include <sys/device.h>

#include <machine/openpromio.h>
#include <machine/autoconf.h>
#include <machine/conf.h>

#include <dev/ofw/openfirm.h>

#define OPROMMAXPARAM		32

static	int lastnode;			/* speed hack */
static	int optionsnode;		/* node ID of ROM's options */

static int openpromcheckid(int, int);
static int openpromgetstr(int, char *, char **);

int
openpromopen(dev_t dev, int flags, int mode, struct proc *p)
{
	return (0);
}

int
openpromclose(dev_t dev, int flags, int mode, struct proc *p)
{
	return (0);
}

/*
 * Verify target ID is valid (exists in the OPENPROM tree), as
 * listed from node ID sid forward.
 */
int
openpromcheckid(int sid, int tid)
{
	for (; sid != 0; sid = OF_peer(sid))
		if (sid == tid || openpromcheckid(OF_child(sid), tid))
			return (1);

	return (0);
}

int
openpromgetstr(int len, char *user, char **cpp)
{
	int error;
	char *cp;

	/* Reject obvious bogus requests */
	if ((u_int)len > (8 * 1024) - 1)
		return (ENAMETOOLONG);

	*cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK);
	error = copyin(user, cp, len);
	cp[len] = '\0';
	return (error);
}

int
openpromioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct opiocdesc *op;
	int node, len, ok, error, s;
	char *name, *value, *nextprop;
	static char buf[32];	/* XXX */

	if (optionsnode == 0) {
		s = splhigh();
		optionsnode = OF_getnodebyname(0, "options");
		splx(s);
	}

	/* All too easy... */
	if (cmd == OPIOCGETOPTNODE) {
		*(int *)data = optionsnode;
		return (0);
	}

	/* Verify node id */
	op = (struct opiocdesc *)data;
	node = op->op_nodeid;
	if (node != 0 && node != lastnode && node != optionsnode) {
		/* Not an easy one, must search for it */
		s = splhigh();
		ok = openpromcheckid(OF_peer(0), node);
		splx(s);
		if (!ok)
			return (EINVAL);
		lastnode = node;
	}

	name = value = NULL;
	error = 0;
	switch (cmd) {

	case OPIOCGET:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		s = splhigh();
		strlcpy(buf, name, 32);	/* XXX */
		len = OF_getproplen(node, buf);
		splx(s);
		if (len > op->op_buflen) {
			error = ENOMEM;
			break;
		}
		op->op_buflen = len;
		/* -1 means no entry; 0 means no value */
		if (len <= 0)
			break;
		value = malloc(len, M_TEMP, M_WAITOK);
		s = splhigh();
		strlcpy(buf, name, 32);	/* XXX */
		OF_getprop(node, buf, value, len);
		splx(s);
		error = copyout(value, op->op_buf, len);
		break;

	case OPIOCSET:
		if ((flags & FWRITE) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		error = openpromgetstr(op->op_buflen, op->op_buf, &value);
		if (error)
			break;
		s = splhigh();
		strlcpy(buf, name, 32);	/* XXX */
		len = OF_setprop(node, buf, value, op->op_buflen + 1);
		splx(s);
		if (len != op->op_buflen)
			error = EINVAL;
		break;

	case OPIOCNEXTPROP:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		if (op->op_buflen <= 0) {
			error = ENAMETOOLONG;
			break;
		}
		value = nextprop = malloc(OPROMMAXPARAM, M_TEMP,
		    M_WAITOK | M_CANFAIL);
		if (nextprop == NULL) {
			error = ENOMEM;
			break;
		}
		s = splhigh();
		strlcpy(buf, name, 32);	/* XXX */
		error = OF_nextprop(node, buf, nextprop);
		splx(s);
		if (error == -1) {
			error = EINVAL;
			break;
		}
		if (error == 0) {
			char nul = '\0';

			op->op_buflen = 0;
			error = copyout(&nul, op->op_buf, sizeof(char));
			break;
		}
		len = strlen(nextprop);
		if (len > op->op_buflen)
			len = op->op_buflen;
		else
			op->op_buflen = len;
		error = copyout(nextprop, op->op_buf, len);
		break;

	case OPIOCGETNEXT:
		if ((flags & FREAD) == 0)
			return (EBADF);
		s = splhigh();
		node = OF_peer(node);
		splx(s);
		*(int *)data = lastnode = node;
		break;

	case OPIOCGETCHILD:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		s = splhigh();
		node = OF_child(node);
		splx(s);
		*(int *)data = lastnode = node;
		break;

	default:
		return (ENOTTY);
	}

	if (name)
		free(name, M_TEMP, 0);
	if (value)
		free(value, M_TEMP, 0);

	return (error);
}


code:
/*	$OpenBSD: rbus_machdep.c,v 1.13 2013/08/07 07:29:19 mpi Exp $ */
/*	$NetBSD: rbus_machdep.c,v 1.2 1999/10/15 06:43:06 haya Exp $	*/

/*
 * Copyright (c) 1999
 *     HAYAKAWA Koichi.  All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <machine/bus.h>
#include <dev/cardbus/rbus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <dev/ofw/openfirm.h>

void macppc_cardbus_init(pci_chipset_tag_t pc, pcitag_t tag);

rbus_tag_t
rbus_pccbb_parent_mem(struct device *self, struct pci_attach_args *pa)
{
	macppc_cardbus_init(pa->pa_pc, pa->pa_tag);

	return (rbus_new_root_share(pa->pa_memt, pa->pa_memex,
	    0x00000000, 0xffffffff));
}

rbus_tag_t
rbus_pccbb_parent_io(struct device *self, struct pci_attach_args *pa)
{
	return (rbus_new_root_share(pa->pa_iot, pa->pa_ioex,
	    0x0000, 0xffff));
}

/*
 * Big ugly hack to enable bridge/fix interrupts
 */
void
macppc_cardbus_init(pci_chipset_tag_t pc, pcitag_t tag)
{
	u_int x;
	static int initted = 0;

	if (initted)
		return;
	initted = 1;

	/* XXX What about other bridges? */

	x = pci_conf_read(pc, tag, PCI_ID_REG);
	if (PCI_VENDOR(x) == PCI_VENDOR_TI &&
	    PCI_PRODUCT(x) == PCI_PRODUCT_TI_PCI1211) {
		/* For CardBus card. */
		pci_conf_write(pc, tag, 0x18, 0x10010100);

		/* Route INTA to MFUNC0 */
		x = pci_conf_read(pc, tag, 0x8c);
		x |= 0x02;
		pci_conf_write(pc, tag, 0x8c, x);

		tag = pci_make_tag(pc, 0, 0, 0);
		x = pci_conf_read(pc, tag, PCI_ID_REG);
		if (PCI_VENDOR(x) == PCI_VENDOR_MOT &&
		    PCI_PRODUCT(x) == PCI_PRODUCT_MOT_MPC106) {
			/* Set subordinate bus number to 1. */
			x = pci_conf_read(pc, tag, 0x40);
			x |= 1 << 8;
			pci_conf_write(pc, tag, 0x40, x);
		}
	}

	if (PCI_VENDOR(x) == PCI_VENDOR_TI &&
	    (PCI_PRODUCT(x) == PCI_PRODUCT_TI_PCI1410 ||
	    PCI_PRODUCT(x) == PCI_PRODUCT_TI_PCI1510)) {
		/* dont mess with the bus numbers or latency timer */

		/* Route INTA to MFUNC0 */
		x = pci_conf_read(pc, tag, 0x8c);
		x |= 0x02;
		pci_conf_write(pc, tag, 0x8c, x);
	}
}

void
pccbb_attach_hook(struct device *parent, struct device *self,
    struct pci_attach_args *pa)
{
	pci_chipset_tag_t pc = pa->pa_pc;
	int node = PCITAG_NODE(pa->pa_tag);
	int bus, busrange[2];

	if (OF_getprop(OF_parent(node), "bus-range", &busrange,
	    sizeof(busrange)) != sizeof(busrange))
		return;

	bus = busrange[0] + 1;
	while (bus < 256 && pc->busnode[bus])
		bus++;
	if (bus == 256)
		return;
	pc->busnode[bus] = node;
}


code:
/*	$OpenBSD: wscons_machdep.c,v 1.6 2008/01/23 16:37:56 jsing Exp $ */

/*
 * Copyright (c) 2001 Aaron Campbell
 * All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR OR HIS RELATIVES 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 MIND, 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.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/extent.h>

#include <machine/bus.h>

#include <dev/cons.h>

#include "wsdisplay.h"
#if NWSDISPLAY > 0
#include <dev/wscons/wsdisplayvar.h>
#endif
#include <dev/wscons/wskbdvar.h>

cons_decl(ws);

void
wscnprobe(struct consdev *cp)
{
	int maj;

	/* locate the major number */
	for (maj = 0; maj < nchrdev; maj++) {
		if (cdevsw[maj].d_open == wsdisplayopen)
			break;
	}

	if (maj == nchrdev) {
		/* we are not in cdevsw[], give up */
		panic("wsdisplay is not in cdevsw[]");
	}

	cp->cn_dev = makedev(maj, 0);
	cp->cn_pri = CN_MIDPRI;
}

void
wscninit(struct consdev *cp)
{
	return;
}

void
wscnputc(dev_t dev, int i)
{
	wsdisplay_cnputc(dev, i);
}

int
wscngetc(dev_t dev)
{
	return (wskbd_cngetc(dev));
}

void
wscnpollc(dev_t dev, int on)
{
	wskbd_cnpollc(dev, on);
}


code: src/sys/arch/macppc/pci

path: sys/arch/macppc/pci/CVS/Repository


code:
/*	$OpenBSD: agp_machdep.c,v 1.3 2014/03/29 18:09:30 guenther Exp $	*/

/*
 * Copyright (c) 2012 Martin Pieuchot <mpi@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/rwlock.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/agpvar.h>

void
agp_flush_cache(void)
{
	__asm volatile("sync" : : : "memory");
}


code:
/*	$OpenBSD: hpb.c,v 1.1 2015/06/02 13:53:43 mpi Exp $	*/

/*
 * Copyright (c) 2015 Martin Pieuchot
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <machine/intr.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/pci/ppbreg.h>

/*
 * Section 7.6.2  Interrupt Message Definition Register
 */
#define PCI_HT_LAST_ISMG		(0x01 << 16)
#define PCI_HT_IMSG_LO(idx)		(((2 * (idx)) + 0x10) << 16)
#define  HT_MASK	(1 << 0)
#define  HT_ACTIVELOW	(1 << 1)
#define  HT_EOI		(1 << 5)

#define PCI_HT_IMSG_HI(idx)		(PCI_HT_IMSG_LO(idx) + 1)
#define  HT_PASSPW	(1U << 30)
#define  HT_WAITEOI	(1U << 31)	/* Waiting for EOI */

/* Apple hardware is special... */
#define HT_APPL_EOIOFF(idx)		(0x60 + (((idx) >> 3) & ~3))
#define	HT_APPL_WEOI(idx)		(1 << ((idx) & 0x1f))

struct ht_intr_msg {
	unsigned int	him_idx;	/* Index */
	int		him_ist;	/* Share type */
	pcireg_t	him_weoi;	/* Cached wait for interrupt data */
};

#define	hpb_MAX_IMSG	128

struct hpb_softc {
	struct device		sc_dev;
	pci_chipset_tag_t	sc_pc;
	pcitag_t		sc_tag;
	pcireg_t		sc_id;		/* Needed for Apple hardware */
	unsigned int		sc_off;		/* Interrupt cap. offset */
	unsigned int		sc_nirq;
	struct ht_intr_msg	sc_imap[hpb_MAX_IMSG];
};

int	hpb_match(struct device *, void *, void *);
void	hpb_attach(struct device *, struct device *, void *);

int	hpb_print(void *, const char *);

void	hpb_eoi(int);
int	hpb_enable_irq(int, int);
int	hpb_disable_irq(int, int);

const struct cfattach hpb_ca = {
	sizeof(struct hpb_softc), hpb_match, hpb_attach
};

struct cfdriver hpb_cd = {
	NULL, "hpb", DV_DULL,
};

int
hpb_match(struct device *parent, void *match, void *aux)
{
	struct pci_attach_args *pa = aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	pcitag_t tag = pa->pa_tag;

	if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE ||
	    PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_PCI)
		return (0);

	if (!pci_get_ht_capability(pc, tag, PCI_HT_CAP_INTR, NULL, NULL))
		return (0);

	return (10);
}

void
hpb_attach(struct device *parent, struct device *self, void *aux)
{
	struct hpb_softc *sc = (struct hpb_softc *)self;
	struct pci_attach_args *pa = aux;
	struct pcibus_attach_args pba;
	pci_chipset_tag_t pc = pa->pa_pc;
	pcitag_t tag = pa->pa_tag;
	int idx, irq, off;
	pcireg_t busdata, reg;

	if (!pci_get_ht_capability(pc, tag, PCI_HT_CAP_INTR, &off, NULL))
		panic("A clown ate your HT capability");

	/* Interrupt definitions are numbered beginning with 0. */
	pci_conf_write(pc, tag, off, PCI_HT_LAST_ISMG);
	reg = pci_conf_read(pc, tag, off + PCI_HT_INTR_DATA);

	sc->sc_pc = pc;
	sc->sc_tag = tag;
	sc->sc_id = pa->pa_id;
	sc->sc_off = off;
	sc->sc_nirq = ((reg >> 16) & 0xff);

	if (sc->sc_nirq == 0 || sc->sc_nirq > hpb_MAX_IMSG)
		return;

	printf(": %u sources\n", sc->sc_nirq);

	for (idx = 0; idx < sc->sc_nirq; idx++) {
		pci_conf_write(pc, tag, off, PCI_HT_IMSG_LO(idx));
		reg = pci_conf_read(pc, tag, off + PCI_HT_INTR_DATA);

		pci_conf_write(pc, tag, off + PCI_HT_INTR_DATA, reg | HT_MASK);
		irq = (reg >> 16) & 0xff;

#ifdef DIAGNOSTIC
		if (sc->sc_imap[irq].him_idx != 0) {
			printf("%s: multiple definition for irq %d\n",
			    sc->sc_dev.dv_xname, irq);
			continue;
		}
#endif
		pci_conf_write(pc, tag, off, PCI_HT_IMSG_HI(idx));
		reg = pci_conf_read(pc, tag, off + PCI_HT_INTR_DATA);

		sc->sc_imap[irq].him_idx = idx;
		sc->sc_imap[irq].him_weoi = reg | HT_WAITEOI;
	}

	busdata = pci_conf_read(pc, pa->pa_tag, PPB_REG_BUSINFO);

	memset(&pba, 0, sizeof(pba));
	pba.pba_busname = "pci";
	pba.pba_iot = pa->pa_iot;
	pba.pba_memt = pa->pa_memt;
	pba.pba_dmat = pa->pa_dmat;
	pba.pba_pc = pc;
	pba.pba_domain = pa->pa_domain;
	pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
	pba.pba_bridgetag = &sc->sc_tag;

	config_found(self, &pba, hpb_print);
}

int
hpb_print(void *aux, const char *pnp)
{
	struct pcibus_attach_args *pba = aux;

	if (pnp)
		printf("%s at %s", pba->pba_busname, pnp);
	printf(" bus %d", pba->pba_bus);
	return (UNCONF);
}

void
hpb_eoi(int irq)
{
	struct hpb_softc *sc = hpb_cd.cd_devs[0];
	pci_chipset_tag_t pc = sc->sc_pc;
	pcitag_t tag = sc->sc_tag;
	int idx;

	if (irq >= sc->sc_nirq || sc->sc_imap[irq].him_weoi == 0 ||
	    sc->sc_imap[irq].him_ist != IST_LEVEL)
		return;

	idx = sc->sc_imap[irq].him_idx;

	if (PCI_VENDOR(sc->sc_id) == PCI_VENDOR_APPLE) {
		pci_conf_write(pc, tag, HT_APPL_EOIOFF(idx), HT_APPL_WEOI(idx));
	} else {
		pci_conf_write(pc, tag, sc->sc_off, PCI_HT_IMSG_HI(idx));
		pci_conf_write(pc, tag, sc->sc_off + PCI_HT_INTR_DATA,
		    sc->sc_imap[irq].him_weoi);
	}
}

int
hpb_enable_irq(int irq, int ist)
{
	struct hpb_softc *sc = hpb_cd.cd_devs[0];
	pci_chipset_tag_t pc = sc->sc_pc;
	pcitag_t tag = sc->sc_tag;
	pcireg_t reg;
	int idx;

	if (irq >= sc->sc_nirq || sc->sc_imap[irq].him_weoi == 0)
		return (0);

	idx = sc->sc_imap[irq].him_idx;
	sc->sc_imap[irq].him_ist = ist;

	pci_conf_write(pc, tag, sc->sc_off, PCI_HT_IMSG_LO(idx));
	reg = pci_conf_read(pc, tag, sc->sc_off + PCI_HT_INTR_DATA);

	pci_conf_write(pc, tag, sc->sc_off + PCI_HT_INTR_DATA, reg | HT_MASK);

	reg &= ~(HT_ACTIVELOW | HT_EOI | HT_MASK);
	if (ist == IST_LEVEL)
		reg |= HT_ACTIVELOW | HT_EOI;

	pci_conf_write(pc, tag, sc->sc_off + PCI_HT_INTR_DATA, reg);

	return (1);
}

int
hpb_disable_irq(int irq, int ist)
{
	struct hpb_softc *sc = hpb_cd.cd_devs[0];
	pci_chipset_tag_t pc = sc->sc_pc;
	pcitag_t tag = sc->sc_tag;
	pcireg_t reg;
	int idx;

	if (irq > sc->sc_nirq || sc->sc_imap[irq].him_weoi == 0)
		return (0);

	idx = sc->sc_imap[irq].him_idx;

	pci_conf_write(pc, tag, sc->sc_off, PCI_HT_IMSG_LO(idx));
	reg = pci_conf_read(pc, tag, sc->sc_off + PCI_HT_INTR_DATA);

	pci_conf_write(pc, tag, sc->sc_off + PCI_HT_INTR_DATA, reg | HT_MASK);

	return (1);
}


code:
/*	$OpenBSD: ht.c,v 1.17 2015/06/25 18:08:53 miod Exp $	*/

/*
 * Copyright (c) 2005 Mark Kettenis
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <machine/autoconf.h>
#include <machine/bus.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <dev/ofw/openfirm.h>

int	 ht_match(struct device *, void *, void *);
void	 ht_attach(struct device *, struct device *, void *);

pcireg_t ht_conf_read(void *, pcitag_t, int);
void	 ht_conf_write(void *, pcitag_t, int, pcireg_t);

int	 ht_print(void *, const char *);

struct ht_softc {
	struct device	sc_dev;
	int		sc_maxdevs;
	struct ppc_bus_space sc_mem_bus_space;
	struct ppc_bus_space sc_io_bus_space;
	struct ppc_pci_chipset sc_pc;
	bus_space_tag_t sc_memt;
	bus_space_handle_t sc_config0_memh;
	bus_space_handle_t sc_config1_memh;
	bus_space_tag_t sc_iot;
	bus_space_handle_t sc_config0_ioh;
};

struct cfattach ht_ca = {
	sizeof(struct ht_softc), ht_match, ht_attach
};

struct cfdriver ht_cd = {
	NULL, "ht", DV_DULL,
};

int
ht_match(struct device *parent, void *cf, void *aux)
{
	struct confargs *ca = aux;

	if (strcmp(ca->ca_name, "ht") == 0)
		return (1);
	return (0);
}

void
ht_attach(struct device *parent, struct device *self, void *aux)
{
	struct ht_softc *sc = (struct ht_softc *)self;
	struct confargs *ca = aux;
	struct pcibus_attach_args pba;
	u_int32_t regs[6];
	char compat[32];
	int node, len;

	if (ca->ca_node == 0) {
		printf(": invalid node on ht config\n");
		return;
	}

	len = OF_getprop(ca->ca_node, "reg", regs, sizeof(regs));
	if (len < 0 || len < sizeof(regs)) {
		printf(": regs lookup failed, node %x\n", ca->ca_node);
		return;
	}

	sc->sc_mem_bus_space.bus_base = 0x80000000;
	sc->sc_mem_bus_space.bus_size = 0;
	sc->sc_mem_bus_space.bus_io = 0;
	sc->sc_memt = &sc->sc_mem_bus_space;

	sc->sc_io_bus_space.bus_base = 0x80000000;
	sc->sc_io_bus_space.bus_size = 0;
	sc->sc_io_bus_space.bus_io = 1;
	sc->sc_iot = &sc->sc_io_bus_space;

	sc->sc_maxdevs = 1;
	for (node = OF_child(ca->ca_node); node; node = OF_peer(node))
		sc->sc_maxdevs++;

	if (bus_space_map(sc->sc_memt, regs[1],
	    (1 << 11)*sc->sc_maxdevs, 0, &sc->sc_config0_memh)) {
		printf(": can't map PCI config0 memory\n");
		return;
	}

	if (bus_space_map(sc->sc_memt, regs[1] + 0x01000000, 0x80000, 0,
	    &sc->sc_config1_memh)) {
		printf(": can't map PCI config1 memory\n");
		return;
	}

	if (bus_space_map(sc->sc_iot, regs[4], 0x1000, 0,
	    &sc->sc_config0_ioh)) {
		printf(": can't map PCI config0 io\n");
		return;
	}

	len = OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat));
	if (len <= 0)
		printf(": unknown");
	else
		printf(": %s", compat);

	sc->sc_pc.pc_conf_v = sc;
	sc->sc_pc.pc_node = ca->ca_node;
	sc->sc_pc.pc_conf_read = ht_conf_read;
	sc->sc_pc.pc_conf_write = ht_conf_write;

	bzero(&pba, sizeof(pba));
	pba.pba_busname = "pci";
	pba.pba_iot = sc->sc_iot;
	pba.pba_memt = sc->sc_memt;
	pba.pba_dmat = &pci_bus_dma_tag;
	pba.pba_pc = &sc->sc_pc;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = 0;

	printf(", %d devices\n", sc->sc_maxdevs);

	config_found(self, &pba, ht_print);
}

pcireg_t
ht_conf_read(void *cpv, pcitag_t tag, int offset)
{
	struct ht_softc *sc = cpv;
	int bus, dev, fcn;
	pcireg_t reg;
	uint32_t val;

	val = PCITAG_OFFSET(tag);
#ifdef DEBUG
	printf("ht_conf_read: tag=%x, offset=%x\n", val, offset);
#endif
	pci_decompose_tag(NULL, tag, &bus, &dev, &fcn);
	if (bus == 0 && dev == 0) {
		val |= (offset << 2);
		reg = bus_space_read_4(sc->sc_iot, sc->sc_config0_ioh, val);
		reg = letoh32(reg);
	} else if (bus == 0) {
		/* XXX Why can we only access function 0? */
		if (fcn > 0)
			return ~0;
		val |= offset;
		reg = bus_space_read_4(sc->sc_memt, sc->sc_config0_memh, val);
	} else {
		val |= offset;
		reg = bus_space_read_4(sc->sc_memt, sc->sc_config1_memh, val);
	}
#ifdef DEBUG
	printf("ht_conf_read: reg=%x\n", reg);
#endif
	return reg;
}

void
ht_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data)
{
	struct ht_softc *sc = cpv;
	int bus, dev, fcn;
	uint32_t val;

	val = PCITAG_OFFSET(tag);
#ifdef DEBUG
	printf("ht_conf_write: tag=%x, offset=%x, data = %x\n",
	       val, offset, data);
#endif
	pci_decompose_tag(NULL, tag, &bus, &dev, &fcn);
	if (bus == 0 && dev == 0) {
		val |= (offset << 2);
		data = htole32(data);
		bus_space_write_4(sc->sc_iot, sc->sc_config0_ioh, val, data);
		bus_space_read_4(sc->sc_iot, sc->sc_config0_ioh, val);
	} else if (bus == 0) {
		/* XXX Why can we only access function 0? */
		if (fcn > 0)
			return;
		val |= offset;
		bus_space_write_4(sc->sc_memt, sc->sc_config0_memh, val, data);
		bus_space_read_4(sc->sc_memt, sc->sc_config0_memh, val);
	} else {
		val |= offset;
		bus_space_write_4(sc->sc_memt, sc->sc_config1_memh, val, data);
		bus_space_read_4(sc->sc_memt, sc->sc_config1_memh, val);
	}
}

int
ht_print(void *aux, const char *pnp)
{
	struct pcibus_attach_args *pba = aux;

	if (pnp)
		printf("%s at %s", pba->pba_busname, pnp);
	printf(" bus %d", pba->pba_bus);
	return (UNCONF);
}


code:
/*	$OpenBSD: kauaiata.c,v 1.10 2008/04/25 14:51:35 jmc Exp $ */

/*
 * Copyright (c) 2003 Dale Rahn
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 *
 */

/*
 * Glue to to attach kauai ata to the macobio_wdc
 * which it heavily resembles.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <dev/ofw/openfirm.h>

#include <machine/autoconf.h>

struct kauaiata_softc {
	struct device sc_dev;
	struct ppc_bus_space sc_membus_space;
	/* XXX */
};

int kauaiatamatch(struct device *parent, void *match, void *aux);
void kauaiataattach(struct device *parent, struct device *self, void *aux);
int kauaiata_print(void *aux, const char *dev);

struct cfattach kauaiata_ca = {
	sizeof(struct kauaiata_softc), kauaiatamatch, kauaiataattach,
};

struct cfdriver kauaiata_cd = {
	NULL, "kauaiata", DV_DULL,
};

int
kauaiatamatch(struct device *parent, void *match, void *aux)
{
	struct pci_attach_args *pa = aux;

	/*
	 * Match the adapter
	 * XXX match routine??
	 */
	switch(PCI_VENDOR(pa->pa_id)) {
	case PCI_VENDOR_APPLE:
		switch (PCI_PRODUCT(pa->pa_id)) {
		case PCI_PRODUCT_APPLE_UNINORTH_ATA:
		case PCI_PRODUCT_APPLE_INTREPID_ATA:
		case PCI_PRODUCT_APPLE_INTREPID2_ATA:
		case PCI_PRODUCT_APPLE_K2_ATA:
		case PCI_PRODUCT_APPLE_SHASTA_ATA:
			return (1);
		}
		break;
	}
	return 0;
}

void
kauaiataattach(struct device *parent, struct device *self, void *aux)
{
	int node;
	struct confargs ca;
	int namelen;
	u_int32_t reg[20];
	char name[32];
	int32_t intr[8];

	struct kauaiata_softc *sc = (struct kauaiata_softc *)self;
	struct pci_attach_args *pa = aux;
	pci_chipset_tag_t pc = pa->pa_pc;

	/* XXX not necessarily the right device */
	node = OF_finddevice("uata");
	if (node == -1)
		node = OF_finddevice("/pci@f4000000/ata-6");

	if (node == -1) {
		printf("\n");
		return;
	}

	/*
	 * XXX - need to compare node and PCI id to verify this is the
	 * correct device.
	 */

	ca.ca_nreg  = OF_getprop(node, "reg", reg, sizeof(reg));

	/*
	 * The PCI Interrupt Configuration Registers seems to be
	 * hardwired to 0.  Get the interrupt line from OpenFirmware.
	 */
	/* XXX */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_APPLE &&
	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_SHASTA_ATA) {
		ca.ca_nintr = OF_getprop(node, "interrupts",
		    intr, sizeof intr);
	} else {
		ca.ca_nintr = 4;
		intr[0] = 0x27;
	}

	namelen = OF_getprop(node, "name", name, sizeof(name));
	if ((namelen < 0) || (namelen >= sizeof(name))) {
		printf(" bad name prop len %x\n", namelen);
		return;
	}

	name[namelen] = 0; /* name property may not be null terminated */

	/* config read */
	sc->sc_membus_space.bus_base =
	    pci_conf_read(pc, pa->pa_tag, PCI_MAPREG_START);

	/* make sure device memory access is enabled */
	{
		bus_space_tag_t		iot;
		bus_space_handle_t	ioh;
		bus_size_t		size;

		if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM, 0,
		    &iot, &ioh, NULL, &size, 0)) {
			printf(": mapping memory failed\n");
			return;
		}

		bus_space_unmap(iot, ioh, size);
	}
#if 0
	pci_conf_write(pc, pa->pa_tag, PCI_MAPREG_START, 0xffffffff);
	size =  ~(pci_conf_read(pc, pa->pa_tag, PCI_MAPREG_START));
	pci_conf_write(pc, pa->pa_tag, PCI_MAPREG_START,
		sc->sc_membus_space.bus_base);
#endif

	ca.ca_baseaddr = sc->sc_membus_space.bus_base;

	ca.ca_name = name;
	ca.ca_iot = &sc->sc_membus_space;
	ca.ca_dmat = pa->pa_dmat;

	ca.ca_reg = reg;
	reg[0] = 0x2000; /* offset to wdc registers */
	reg[1] = reg[9] - 0x2000; /* map size of wdc registers */
	reg[2] = 0x1000; /* offset to dbdma registers */
	reg[3] = 0x1000; /* map size of dbdma registers */
	ca.ca_intr = intr;

	printf("\n");

	config_found(self, &ca, kauaiata_print);
}

int
kauaiata_print(void *aux, const char *dev)
{
	return QUIET;
}


code:
/*	$OpenBSD: macobio.c,v 1.21 2015/04/02 11:12:24 mpi Exp $	*/
/*	$NetBSD: obio.c,v 1.6 1999/05/01 10:36:08 tsubai Exp $	*/

/*-
 * Copyright (C) 1998	Internet Research Institute, Inc.
 * All rights reserved.
 *
 * 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
 *	Internet Research Institute, Inc.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <dev/ofw/openfirm.h>

#include <machine/bus.h>
#include <machine/autoconf.h>
#include <macppc/pci/macobio.h>

void macobio_attach(struct device *, struct device *, void *);
int macobio_match(struct device *, void *, void *);
int macobio_print(void *, const char *);
void macobio_modem_power(int enable);

struct macobio_softc {
	struct device sc_dev;
	int sc_node;
	struct ppc_bus_space sc_membus_space;
	int	sc_id; /* copy of the PCI pa_id */
	u_int8_t *obiomem;
};
struct cfdriver macobio_cd = {
	NULL, "macobio", DV_DULL,
};

struct cfattach macobio_ca = {
	sizeof(struct macobio_softc), macobio_match, macobio_attach
};

int
macobio_match(struct device *parent, void *cf, void *aux)
{
	struct pci_attach_args *pa = aux;

	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_APPLE)
		switch (PCI_PRODUCT(pa->pa_id)) {

		case PCI_PRODUCT_APPLE_GC:
		case PCI_PRODUCT_APPLE_OHARE:
		case PCI_PRODUCT_APPLE_HEATHROW:
		case PCI_PRODUCT_APPLE_PADDINGTON:
		case PCI_PRODUCT_APPLE_KEYLARGO:
		case PCI_PRODUCT_APPLE_INTREPID:
		case PCI_PRODUCT_APPLE_PANGEA_MACIO:
		case PCI_PRODUCT_APPLE_SHASTA:
		case PCI_PRODUCT_APPLE_K2_MACIO:
			return 1;
		}

	return 0;
}

#define HEATHROW_FCR_OFFSET 0x38
u_int32_t *heathrow_FCR = NULL;

/*
 * Attach all the sub-devices we can find
 */
void
macobio_attach(struct device *parent, struct device *self, void *aux)
{
	struct macobio_softc *sc = (struct macobio_softc *)self;
	struct pci_attach_args *pa = aux;
	struct confargs ca;
	int node, child, namelen;
	u_int32_t reg[20];
	int32_t intr[8];
	char name[32];
	int need_interrupt_controller = 0;

	sc->sc_id = pa->pa_id; /* save of type for later */

	switch (PCI_PRODUCT(pa->pa_id)) {

	/* XXX should not use name */
	case PCI_PRODUCT_APPLE_GC:
		node = OF_finddevice("/bandit/gc");
		need_interrupt_controller = 1;
		break;

	case PCI_PRODUCT_APPLE_OHARE:
		node = OF_finddevice("/bandit/ohare");
		need_interrupt_controller = 1;
		break;

	case PCI_PRODUCT_APPLE_HEATHROW:
	case PCI_PRODUCT_APPLE_PADDINGTON:
		node = OF_finddevice("mac-io");
		if (node == -1)
			node = OF_finddevice("/pci/mac-io");
		if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg))
			== (sizeof (reg[0]) * 5))
		{
			/* always ??? */
			heathrow_FCR = mapiodev(reg[2] + HEATHROW_FCR_OFFSET,
			    4);
		}
		break;
	case PCI_PRODUCT_APPLE_KEYLARGO:
	case PCI_PRODUCT_APPLE_INTREPID:
	case PCI_PRODUCT_APPLE_PANGEA_MACIO:
	case PCI_PRODUCT_APPLE_SHASTA:
	case PCI_PRODUCT_APPLE_K2_MACIO:
		node = OF_finddevice("mac-io");
		if (node == -1)
			node = OF_finddevice("/pci/mac-io");
		if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg))
		    == (sizeof (reg[0]) * 5))
			 sc->obiomem = mapiodev(reg[2], 0x100);
		break;
	default:
		printf(": unknown macobio controller\n");
		return;
	}
	sc->sc_node = node;

	if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg)) < 12)
		return;

	ca.ca_baseaddr = reg[2];

	sc->sc_membus_space.bus_base = ca.ca_baseaddr;

	ca.ca_iot = &sc->sc_membus_space;
	ca.ca_dmat = pa->pa_dmat;

	printf("\n");

	/*
	 * This might be a hack, but it makes the interrupt controller
	 * attach as expected if a device node existed in the OF tree.
	 */
	if (need_interrupt_controller) {
		/* force attachment of legacy interrupt controllers */
		ca.ca_name = "legacy-interrupt-controller";
		ca.ca_node = 0;

		ca.ca_nreg  = 0;
		ca.ca_nintr = 0;

		ca.ca_reg = NULL;
		ca.ca_intr = NULL;

		config_found(self, &ca, macobio_print);
	}

	for (child = OF_child(node); child; child = OF_peer(child)) {
		namelen = OF_getprop(child, "name", name, sizeof(name));
		if (namelen < 0)
			continue;
		if (namelen >= sizeof(name))
			continue;

		name[namelen] = 0;
		ca.ca_name = name;
		ca.ca_node = child;

		ca.ca_nreg  = OF_getprop(child, "reg", reg, sizeof(reg));
		ca.ca_nintr = OF_getprop(child, "AAPL,interrupts", intr,
				sizeof(intr));
		if (ca.ca_nintr == -1)
			ca.ca_nintr = OF_getprop(child, "interrupts", intr,
					sizeof(intr));

		ca.ca_reg = reg;
		ca.ca_intr = intr;

		config_found(self, &ca, macobio_print);
	}
}

int
macobio_print(void *aux, const char *macobio)
{
	struct confargs *ca = aux;

	if (macobio)
		printf("\"%s\" at %s", ca->ca_name, macobio);

	if (ca->ca_nreg > 0)
		printf(" offset 0x%x", ca->ca_reg[0]);

	return UNCONF;
}

void *
mac_intr_establish(void * lcv, int irq, int type, int level,
    int (*ih_fun)(void *), void *ih_arg, const char *name)
{
	return (*intr_establish_func)(lcv, irq, type, level, ih_fun,
	    ih_arg, name);
}
void
mac_intr_disestablish(void *lcp, void *arg)
{
	(*intr_disestablish_func)(lcp, arg);
}

void
macobio_enable(int offset, u_int32_t bits)
{
	struct macobio_softc *sc = macobio_cd.cd_devs[0];
	if (sc->obiomem == 0)
		return;

	bits |=  in32rb(sc->obiomem + offset);
	out32rb(sc->obiomem + offset, bits);
}
void
macobio_disable(int offset, u_int32_t bits)
{
	struct macobio_softc *sc = macobio_cd.cd_devs[0];
	if (sc->obiomem == 0)
		return;

	bits =  in32rb(sc->obiomem + offset) & ~bits;
	out32rb(sc->obiomem + offset, bits);
}

uint8_t
macobio_read(int offset)
{
	struct macobio_softc *sc = macobio_cd.cd_devs[0];
	if (sc->obiomem == 0)
		return -1;

	return in8rb(sc->obiomem + offset);
}

void
macobio_write(int offset, uint8_t bits)
{
	struct macobio_softc *sc = macobio_cd.cd_devs[0];
	if (sc->obiomem == 0)
		return;

	out8rb(sc->obiomem + offset, bits);
}

void
macobio_modem_power(int enable)
{
	u_int32_t val;
	struct macobio_softc *sc = macobio_cd.cd_devs[0];
	if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_KEYLARGO ||
	    PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_INTREPID) {
		val = in32rb(sc->obiomem + 0x40);
		if (enable)
			val = val & ~((u_int32_t)1<<25);
		else
			val = val | ((u_int32_t)1<<25);
		out32rb(sc->obiomem + 0x40, val);
	}
	if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_PANGEA_MACIO) {
		if (enable) {
			/* set reset */
			out8(sc->obiomem + 0x006a + 0x03, 0x04);
			/* power modem on */
			out8(sc->obiomem + 0x006a + 0x02, 0x04);
			/* unset reset */
			out8(sc->obiomem + 0x006a + 0x03, 0x05);
		}  else {
			/* disable it how? */
		}
	}
}


code:
/*	$OpenBSD: macobio.h,v 1.2 2012/12/10 16:32:13 mpi Exp $	*/
/*
 * Copyright (c) 2011 Martin Pieuchot <mp@nolizard.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _MACOBIO_H_
#define _MACOBIO_H_

#define GPIO_DDR_INPUT	0x00
#define GPIO_DDR_OUTPUT	0x04

#define GPIO_DATA	0x01	/* Data */
#define GPIO_LEVEL	0x02	/* Pin level (RO) */

void		macobio_enable(int, u_int32_t);
void		macobio_disable(int, u_int32_t);
uint8_t		macobio_read(int);
void		macobio_write(int, uint8_t);

#endif /* _MACOBIO_H_ */


code:
/*	$OpenBSD: mpcpcibus.c,v 1.47 2015/06/03 08:41:43 mpi Exp $ */

/*
 * Copyright (c) 1997 Per Fogelstrom
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 *
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/extent.h>

#include <machine/autoconf.h>
#include <machine/pcb.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <dev/ofw/openfirm.h>

int	mpcpcibrmatch(struct device *, void *, void *);
void	mpcpcibrattach(struct device *, struct device *, void *);

pcireg_t mpc_conf_read(void *, pcitag_t, int);
void	mpc_conf_write(void *, pcitag_t, int, pcireg_t);

u_int32_t mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset);

struct pcibr_config {
	bus_space_tag_t		lc_memt;
	bus_space_tag_t		lc_iot;
	bus_space_handle_t	ioh_cf8;
	bus_space_handle_t	ioh_cfc;
	struct ppc_pci_chipset	lc_pc;
	int			config_type;
};

struct pcibr_softc {
	struct device		sc_dev;
	struct ppc_bus_space	sc_membus_space;
	struct ppc_bus_space	sc_iobus_space;
	struct pcibr_config	pcibr_config;
	struct extent 		*sc_ioex;
	struct extent		*sc_memex;
	char			sc_ioex_name[32];
	char			sc_memex_name[32];
};

struct cfattach mpcpcibr_ca = {
        sizeof(struct pcibr_softc), mpcpcibrmatch, mpcpcibrattach,
};

struct cfdriver mpcpcibr_cd = {
	NULL, "mpcpcibr", DV_DULL,
};

static int      mpcpcibrprint(void *, const char *pnp);

void	mpcpcibus_find_ranges_32(struct pcibr_softc *, u_int32_t *, int);
void	mpcpcibus_find_ranges_64(struct pcibr_softc *, u_int32_t *, int);

/*
 * config types
 * bit meanings
 * 0 - standard cf8/cfc type configurations,
 *     sometimes the base addresses for these are different
 * 1 - Config Method #2 configuration - uni-north
 *
 * 2 - 64 bit config bus, data for accesses &4 is at daddr+4;
 */
struct config_type{
	char * compat;
	u_int32_t addr;	/* offset */
	u_int32_t data;	/* offset */
	int config_type;
};
struct config_type config_offsets[] = {
	{"grackle",		0x00c00cf8, 0x00e00cfc, 0 },
	{"bandit",		0x00800000, 0x00c00000, 1 },
	{"uni-north",		0x00800000, 0x00c00000, 3 },
	{"u3-agp",		0x00800000, 0x00c00000, 3 },
	{"u3-ht",		0x00000cf8, 0x00000cfc, 3 },
	{"u4-pcie",		0x00800000, 0x00c00000, 7 },
	{"legacy",		0x00000cf8, 0x00000cfc, 0 },
	{"IBM,27-82660",	0x00000cf8, 0x00000cfc, 0 },
	{NULL,			0x00000000, 0x00000000, 0 },
};

int
mpcpcibrmatch(struct device *parent, void *match, void *aux)
{
	struct confargs *ca = aux;
	int found = 0;

	if (strcmp(ca->ca_name, mpcpcibr_cd.cd_name) != 0)
		return (found);

	found = 1;

	return found;
}

struct ranges_32 {
	u_int32_t cspace;
	u_int32_t child_hi;
	u_int32_t child_lo;
	u_int32_t phys;
	u_int32_t size_hi;
	u_int32_t size_lo;
};

void
mpcpcibus_find_ranges_32(struct pcibr_softc *sc, u_int32_t *range_store,
    int rangesize)
{
	int i, found;
	unsigned int base = 0;
	unsigned int size = 0;
	struct ranges_32 *prange = (void *)range_store;
	int rangelen;

	rangelen = rangesize / sizeof(struct ranges_32);

	/* mac configs */
	sc->sc_membus_space.bus_base = 0;
	sc->sc_membus_space.bus_io = 0;
	sc->sc_iobus_space.bus_base = 0;
	sc->sc_iobus_space.bus_io = 1;

	/* find io(config) base, flag == 0x01000000 */
	found = 0;
	for (i = 0; i < rangelen; i++) {
		if (prange[i].cspace == 0x01000000) {
			/* find last? */
			found = i;

			if (sc->sc_ioex)
				extent_free(sc->sc_ioex, prange[i].child_lo,
				    prange[i].size_lo, EX_NOWAIT);
		}
	}
	/* found the io space ranges */
	if (prange[found].cspace == 0x01000000) {
		sc->sc_iobus_space.bus_base = prange[found].phys;
		sc->sc_iobus_space.bus_size = prange[found].size_lo;
	}

	/* the mem space ranges
	 * apple openfirmware always puts full
	 * addresses in config information,
	 * it is not necessary to have correct bus
	 * base address, but since 0 is reserved
	 * and all IO and device memory will be in
	 * upper 2G of address space, set to
	 * 0x80000000
	 */
	for (i = 0; i < rangelen; i++) {
		if (prange[i].cspace == 0x02000000) {
#ifdef DEBUG_PCI
			printf("\nfound mem %x %x",
				prange[i].phys,
				prange[i].size_lo);
#endif
			if (base != 0) {
				if ((base + size) == prange[i].phys)
					size += prange[i].size_lo;
				else {
					base = prange[i].phys;
					size = prange[i].size_lo;
				}
			} else {
				base = prange[i].phys;
				size = prange[i].size_lo;
			}

			if (sc->sc_memex)
				extent_free(sc->sc_memex, prange[i].child_lo,
				    prange[i].size_lo, EX_NOWAIT);
		}
	}
	sc->sc_membus_space.bus_base = base;
	sc->sc_membus_space.bus_size = size;
}

struct ranges_64 {
	u_int32_t cspace;
	u_int32_t child_hi;
	u_int32_t child_lo;
	u_int32_t phys_hi;
	u_int32_t phys_lo;
	u_int32_t size_hi;
	u_int32_t size_lo;
};

void
mpcpcibus_find_ranges_64(struct pcibr_softc *sc, u_int32_t *range_store,
    int rangesize)
{
	int i, found;
	unsigned int base = 0;
	unsigned int size = 0;
	struct ranges_64 *prange = (void *)range_store;
	int rangelen;

	rangelen = rangesize / sizeof(struct ranges_64);

	/* mac configs */
	sc->sc_membus_space.bus_base = 0;
	sc->sc_membus_space.bus_io = 0;
	sc->sc_iobus_space.bus_base = 0;
	sc->sc_iobus_space.bus_io = 1;

	if (prange[0].cspace == 0xabb10113) { /* appl U3; */
		prange[0].cspace = 0x01000000;
		prange[0].child_lo = 0x00000000;
		prange[0].phys_lo = 0xf8070000;
		prange[0].size_lo = 0x00001000;
		prange[1].cspace = 0x02000000;
		prange[1].child_lo = 0xf2000000;
		prange[1].phys_lo = 0xf2000000;
		prange[1].size_lo = 0x02800000;
		rangelen = 2;
	}

	/* find io(config) base, flag == 0x01000000 */
	found = 0;
	for (i = 0; i < rangelen; i++) {
		if (prange[i].cspace == 0x01000000) {
			/* find last? */
			found = i;

			if (sc->sc_ioex)
				extent_free(sc->sc_ioex, prange[i].child_lo,
				    prange[i].size_lo, EX_NOWAIT);
		}
	}
	/* found the io space ranges */
	if (prange[found].cspace == 0x01000000) {
		sc->sc_iobus_space.bus_base = prange[found].phys_lo;
		sc->sc_iobus_space.bus_size = prange[found].size_lo;
	}

	/* the mem space ranges
	 * apple openfirmware always puts full
	 * addresses in config information,
	 * it is not necessary to have correct bus
	 * base address, but since 0 is reserved
	 * and all IO and device memory will be in
	 * upper 2G of address space, set to
	 * 0x80000000
	 */
	for (i = 0; i < rangelen; i++) {
		if (prange[i].cspace == 0x02000000) {
#ifdef DEBUG_PCI
			printf("\nfound mem %x %x",
				prange[i].phys_lo,
				prange[i].size_lo);
#endif
			if (base != 0) {
				if ((base + size) == prange[i].phys_lo) {
					size += prange[i].size_lo;
				} else {
					base = prange[i].phys_lo;
					size = prange[i].size_lo;
				}
			} else {
				base = prange[i].phys_lo;
				size = prange[i].size_lo;
			}

			if (sc->sc_memex)
				extent_free(sc->sc_memex, prange[i].child_lo,
				    prange[i].size_lo, EX_NOWAIT);
		}
	}
	sc->sc_membus_space.bus_base = base;
	sc->sc_membus_space.bus_size = size;
}

void
mpcpcibrattach(struct device *parent, struct device *self, void *aux)
{
	struct pcibr_softc *sc = (struct pcibr_softc *)self;
	struct confargs *ca = aux;
	struct pcibr_config *lcp;
	struct pcibus_attach_args pba;
	int of_node = 0;
	char compat[32];
	u_int32_t addr_offset;
	u_int32_t data_offset;
	int i;
	int len;
	int rangesize;
	u_int32_t range_store[32];

	if (ca->ca_node == 0) {
		printf("invalid node on mpcpcibr config\n");
		return;
	}
	len=OF_getprop(ca->ca_node, "name", compat, sizeof (compat));
	compat[len] = '\0';
	if (len > 0)
		printf(" %s", compat);

	len=OF_getprop(ca->ca_node, "compatible", compat,
	    sizeof (compat));
	if (len <= 0 ) {
		len=OF_getprop(ca->ca_node, "name", compat,
			sizeof (compat));
		if (len <= 0) {
			printf(" compatible and name not found\n");
			return;
		}
		compat[len] = 0;
		if (strcmp (compat, "bandit") != 0) {
			printf(" compatible not found and name %s found\n",
			    compat);
			return;
		}
	}
	compat[len] = 0;
	if ((rangesize = OF_getprop(ca->ca_node, "ranges",
	    range_store, sizeof (range_store))) <= 0) {
		if (strcmp(compat, "u3-ht") == 0) {
			range_store[0] = 0xabb10113; /* appl U3; */
		} else
			printf("range lookup failed, node %x\n", ca->ca_node);
	}
	/* translate byte(s) into item count*/

	lcp = &sc->pcibr_config;

	snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name),
	    "%s pciio", sc->sc_dev.dv_xname);
	sc->sc_ioex = extent_create(sc->sc_ioex_name, 0x00000000, 0xffffffff,
	    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
	snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name),
	    "%s pcimem", sc->sc_dev.dv_xname);
	sc->sc_memex = extent_create(sc->sc_memex_name, 0x00000000, 0xffffffff,
	    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);

	if (ppc_proc_is_64b)
		mpcpcibus_find_ranges_64 (sc, range_store, rangesize);
	else
		mpcpcibus_find_ranges_32 (sc, range_store, rangesize);

	addr_offset = 0;
	for (i = 0; config_offsets[i].compat != NULL; i++) {
		struct config_type *co = &config_offsets[i];
		if (strcmp(co->compat, compat) == 0) {
			addr_offset = co->addr;
			data_offset = co->data;
			lcp->config_type = co->config_type;
			break;
		}
	}
	if (addr_offset == 0) {
		printf("unable to find match for"
		    " compatible %s\n", compat);
		return;
	}
#ifdef DEBUG_FIXUP
	printf(" mem base %x sz %x io base %x sz %x\n"
	    " config addr %x config data %x\n",
	    sc->sc_membus_space.bus_base,
	    sc->sc_membus_space.bus_size,
	    sc->sc_iobus_space.bus_base,
	    sc->sc_iobus_space.bus_size,
	    addr_offset, data_offset);
#endif

	if ( bus_space_map(&(sc->sc_iobus_space), addr_offset,
		NBPG, 0, &lcp->ioh_cf8) != 0 )
		panic("mpcpcibus: unable to map self");

	if ( bus_space_map(&(sc->sc_iobus_space), data_offset,
		NBPG, 0, &lcp->ioh_cfc) != 0 )
		panic("mpcpcibus: unable to map self");

	of_node = ca->ca_node;

	lcp->lc_pc.pc_conf_v = lcp;
	lcp->lc_pc.pc_node = ca->ca_node;
	lcp->lc_pc.pc_conf_read = mpc_conf_read;
	lcp->lc_pc.pc_conf_write = mpc_conf_write;
	lcp->lc_iot = &sc->sc_iobus_space;
	lcp->lc_memt = &sc->sc_membus_space;

	printf(": %s\n", compat);

	bzero(&pba, sizeof(pba));
	pba.pba_dmat = &pci_bus_dma_tag;

	pba.pba_busname = "pci";
	pba.pba_iot = &sc->sc_iobus_space;
	pba.pba_memt = &sc->sc_membus_space;
	pba.pba_ioex = sc->sc_ioex;
	pba.pba_memex = sc->sc_memex;
	pba.pba_pc = &lcp->lc_pc;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = 0;

	config_found(self, &pba, mpcpcibrprint);
}

static int
mpcpcibrprint(void *aux, const char *pnp)
{
	struct pcibus_attach_args *pba = aux;

	if (pnp)
		printf("%s at %s", pba->pba_busname, pnp);
	printf(" bus %d", pba->pba_bus);
	return(UNCONF);
}

u_int32_t
mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset)
{
	struct pcibr_config *cp = cpv;
	unsigned int bus, dev, fcn;
	u_int32_t reg, val = PCITAG_OFFSET(tag);

	pci_decompose_tag(cpv, tag, &bus, &dev, &fcn);

	if (cp->config_type & 4) {
		reg = val | offset | 1;
		reg |= (offset >> 8) << 28;
	} else if (cp->config_type & 1) {
		/* Config Mechanism #2 */
		if (bus == 0) {
			if (dev < 11)
				return 0xffffffff;
			/*
			 * Need to do config type 0 operation
			 *  1 << (11?+dev) | fcn << 8 | reg
			 * 11? is because pci spec states
			 * that 11-15 is reserved.
			 */
			reg = 1 << (dev) | fcn << 8 | offset;
		} else {
			if (dev > 15)
				return 0xffffffff;
			/*
			 * config type 1
			 */
			reg = val | offset | 1;
		}
	} else {
		/* config mechanism #2, type 0
		 * standard cf8/cfc config
		 */
		reg =  0x80000000 | val | offset;
	}

	return reg;
}

/* #define DEBUG_CONFIG  */
pcireg_t
mpc_conf_read(void *cpv, pcitag_t tag, int offset)
{
	struct pcibr_config *cp = cpv;
	pcireg_t data;
	u_int32_t reg;
	int s;
	int daddr = 0;
	faultbuf env;
	void *oldh;

	if (offset & 3 ||
	    offset < 0 || offset >= PCI_CONFIG_SPACE_SIZE) {
#ifdef DEBUG_CONFIG
		printf ("pci_conf_read: bad reg %x\n", offset);
#endif /* DEBUG_CONFIG */
		return(~0);
	}

	reg = mpc_gen_config_reg(cpv, tag, offset);
	/* if invalid tag, return -1 */
	if (reg == 0xffffffff)
		return(~0);

	if ((cp->config_type & 2) && (offset & 0x04))
		daddr += 4;

	s = splhigh();

	oldh = curpcb->pcb_onfault;
	if (setfault(&env)) {
		/* we faulted during the read? */
		curpcb->pcb_onfault = oldh;
		splx(s);
		return 0xffffffff;
	}

	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
	data = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, daddr);
	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */

	curpcb->pcb_onfault = oldh;

	splx(s);
#ifdef DEBUG_CONFIG
	if (!((offset == 0) && (data == 0xffffffff))) {
		unsigned int bus, dev, fcn;
		pci_decompose_tag(cpv, tag, &bus, &dev, &fcn);
		printf("mpc_conf_read bus %x dev %x fcn %x offset %x", bus, dev, fcn,
			offset);
		printf(" daddr %x reg %x",daddr, reg);
		printf(" data %x\n", data);
	}
#endif

	return(data);
}

void
mpc_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data)
{
	struct pcibr_config *cp = cpv;
	u_int32_t reg;
	int s;
	int daddr = 0;

	reg = mpc_gen_config_reg(cpv, tag, offset);

	/* if invalid tag, return ??? */
	if (reg == 0xffffffff)
		return;

	if ((cp->config_type & 2) && (offset & 0x04))
		daddr += 4;

#ifdef DEBUG_CONFIG
	{
		unsigned int bus, dev, fcn;
		pci_decompose_tag(cpv, tag, &bus, &dev, &fcn);
		printf("mpc_conf_write bus %x dev %x fcn %x offset %x", bus,
			dev, fcn, offset);
		printf(" daddr %x reg %x",daddr, reg);
		printf(" data %x\n", data);
	}
#endif

	s = splhigh();

	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
	bus_space_write_4(cp->lc_iot, cp->ioh_cfc, daddr, data);
	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */

	splx(s);
}


code:
/*	$OpenBSD: pchb.c,v 1.14 2014/03/26 14:41:41 mpi Exp $	*/
/*	$NetBSD: pchb.c,v 1.4 2000/01/25 07:19:11 tsubai Exp $	*/

/*-
 * Copyright (c) 1996 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/rwlock.h>

#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <dev/pci/agpvar.h>

#include "agp.h"

int	pchbmatch(struct device *, void *, void *);
void	pchbattach(struct device *, struct device *, void *);

struct cfattach pchb_ca = {
	sizeof(struct device), pchbmatch, pchbattach
};

struct cfdriver pchb_cd = {
	NULL, "pchb", DV_DULL
};

int
pchbmatch(struct device *parent, void *cf, void *aux)
{
	struct pci_attach_args *pa = aux;

	/*
	 * Match all known PCI host chipsets.
	 */
	switch (PCI_VENDOR(pa->pa_id)) {
	case PCI_VENDOR_APPLE:
		switch (PCI_PRODUCT(pa->pa_id)) {
		case PCI_PRODUCT_APPLE_BANDIT:
		case PCI_PRODUCT_APPLE_UNINORTH:
		case PCI_PRODUCT_APPLE_UNINORTHETH:
		case PCI_PRODUCT_APPLE_UNINORTH_AGP:
		case PCI_PRODUCT_APPLE_PANGEA:
		case PCI_PRODUCT_APPLE_PANGEA_PCI:
		case PCI_PRODUCT_APPLE_PANGEA_AGP:
		case PCI_PRODUCT_APPLE_UNINORTH2:
		case PCI_PRODUCT_APPLE_UNINORTH2ETH:
		case PCI_PRODUCT_APPLE_UNINORTH2_AGP:
		case PCI_PRODUCT_APPLE_UNINORTH_AGP3:
		case PCI_PRODUCT_APPLE_UNINORTH5:
		case PCI_PRODUCT_APPLE_UNINORTH6:
		case PCI_PRODUCT_APPLE_SHASTA_HT:
		case PCI_PRODUCT_APPLE_K2:
		case PCI_PRODUCT_APPLE_INTREPID2_AGP:
		case PCI_PRODUCT_APPLE_INTREPID2_PCI1:
		case PCI_PRODUCT_APPLE_INTREPID2_PCI2:
		case PCI_PRODUCT_APPLE_U3_AGP:
		case PCI_PRODUCT_APPLE_U3L_AGP:
		case PCI_PRODUCT_APPLE_K2_AGP:
			return (1);
		}
		break;

	case PCI_VENDOR_MOT:
		switch (PCI_PRODUCT(pa->pa_id)) {
		case PCI_PRODUCT_MOT_MPC106:
			return (1);
		}
		break;
	}

	return (0);
}

/*ARGSUSED*/
void
pchbattach(struct device *parent, struct device  *self, void *aux)
{
#if NAGP > 0
	struct pci_attach_args *pa = aux;
#endif /* NAGP > 0 */

	printf("\n");

#if NAGP > 0
	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
	    NULL, NULL) != 0) {
		struct agp_attach_args	aa;
		aa.aa_busname = "agp";
		aa.aa_pa = pa;

		config_found(self, &aa, agpdev_print);
	}
#endif /* NAGP > 0 */
}


code:
/*	$OpenBSD: pci_machdep.c,v 1.6 2015/03/30 13:54:14 mpi Exp $	*/

/*
 * Copyright (c) 2013 Martin Pieuchot
 * Copyright (c) 1997 Per Fogelstrom
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <machine/bus.h>
#include <machine/autoconf.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>

#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>

struct powerpc_bus_dma_tag pci_bus_dma_tag = {
	NULL,
	_dmamap_create,
	_dmamap_destroy,
	_dmamap_load,
	_dmamap_load_mbuf,
	_dmamap_load_uio,
	_dmamap_load_raw,
	_dmamap_unload,
	_dmamap_sync,
	_dmamem_alloc,
	_dmamem_alloc_range,
	_dmamem_free,
	_dmamem_map,
	_dmamem_unmap,
	_dmamem_mmap
};

void
pci_attach_hook(struct device *parent, struct device *self,
    struct pcibus_attach_args *pba)
{
}

int
pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
{
	return (32);
}

pcitag_t
pci_make_tag(pci_chipset_tag_t pc, int b, int d, int f)
{
	struct ofw_pci_register reg;
	pcitag_t tag;
	int node, busrange[2];

	if (pc->busnode[b])
		return PCITAG_CREATE(0, b, d, f);

	node = pc->pc_node;

	/*
	 * Because ht(4) controller nodes do not have a "bus-range"
	 * property,  we need to start iterating from one of their
	 * PCI bridge nodes to be able to find our devices.
	 */
	if (OF_getprop(node, "bus-range", &busrange, sizeof(busrange)) < 0)
		node = OF_child(pc->pc_node);

	for (; node; node = OF_peer(node)) {
		/*
		 * Check for PCI-PCI bridges.  If the device we want is
		 * in the bus-range for that bridge, work our way down.
		 */
		while ((OF_getprop(node, "bus-range", &busrange,
			sizeof(busrange)) == sizeof(busrange)) &&
			(b >= busrange[0] && b <= busrange[1])) {
			node = OF_child(node);
		}

		if (OF_getprop(node, "reg", &reg, sizeof(reg)) < sizeof(reg))
			continue;

		if (b != OFW_PCI_PHYS_HI_BUS(reg.phys_hi))
			continue;
		if (d != OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi))
			continue;
		if (f != OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi))
			continue;

		tag = PCITAG_CREATE(node, b, d, f);

		return (tag);
	}

	return (PCITAG_CREATE(-1, b, d, f));
}

void
pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *b, int *d, int *f)
{
	if (b != NULL)
		*b = PCITAG_BUS(tag);
	if (d != NULL)
		*d = PCITAG_DEV(tag);
	if (f != NULL)
		*f = PCITAG_FUN(tag);
}

int
pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag)
{
	return (PCI_CONFIG_SPACE_SIZE);
}

pcireg_t
pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
{
        if (PCITAG_NODE(tag) != -1)
		return (*(pc)->pc_conf_read)(pc->pc_conf_v, tag, reg);

        return ((pcireg_t)~0);
}

void
pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
{
        if (PCITAG_NODE(tag) != -1)
		(*(pc)->pc_conf_write)(pc->pc_conf_v, tag, reg, data);
}

int
pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	struct ofw_pci_register reg;
	int node = PCITAG_NODE(pa->pa_tag);
	int intr[4], len;

	if (OF_getprop(node, "reg", &reg, sizeof(reg)) < sizeof(reg))
		return (ENODEV);

	/* Try to get the old Apple OFW interrupt property first. */
	len = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr));
	if (len == sizeof(intr[0]))
		goto found;

	len = OF_getprop(node, "interrupts", intr, sizeof(intr));
	if (len < sizeof(intr[0]))
		return (ENODEV);

	reg.size_hi = intr[0];
	if (ofw_intr_map(OF_parent(node), (uint32_t *)&reg, intr)) {
		/*
		 * This can fail on some machines where the parent's
		 * node doesn't have any "interrupt-map" and friends.
		 *
		 * In this case just trust what we got in "interrupts".
		 */
	}

found:
	*ihp = intr[0];

	return (0);
}

int
pci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	return (-1);
}

int
pci_intr_line(pci_chipset_tag_t pc, pci_intr_handle_t ih)
{
	return (ih);
}

const char *
pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih)
{
	static char str[16];

	snprintf(str, sizeof(str), "irq %ld", ih);

	return (str);
}

void *
pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int lvl,
    int (*func)(void *), void *arg, const char *what)
{
	return (*intr_establish_func)(pc, ih, IST_LEVEL, lvl, func, arg, what);
}

void
pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
{
	(*intr_disestablish_func)(pc, cookie);
}

int
pci_ether_hw_addr(pci_chipset_tag_t pc, uint8_t *oaddr)
{
	uint8_t laddr[6];
	int node, len;

	node = OF_finddevice("enet");
	len = OF_getprop(node, "local-mac-address", laddr, sizeof(laddr));
	if (sizeof(laddr) == len) {
		memcpy(oaddr, laddr, sizeof(laddr));
		return (1);
	}

	oaddr[0] = oaddr[1] = oaddr[2] = 0xff;
	oaddr[3] = oaddr[4] = oaddr[5] = 0xff;

	return (0);
}

int
ofw_enumerate_pcibus(struct pci_softc *sc,
    int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
{
	pci_chipset_tag_t pc = sc->sc_pc;
	struct ofw_pci_register reg;
	int len, node, b, d, f, ret;
	char compat[32];
	pcireg_t bhlcr;
	pcitag_t tag;

	if (sc->sc_bridgetag)
		node = PCITAG_NODE(*sc->sc_bridgetag);
	else
		node = pc->pc_node;

	/* The AGP bridge is not in the device-tree. */
	len = OF_getprop(node, "compatible", compat, sizeof(compat));
	if (len > 0 && strcmp(compat, "u3-agp") == 0) {
		tag = PCITAG_CREATE(0, sc->sc_bus, 11, 0);
		ret = pci_probe_device(sc, tag, match, pap);
		if (match != NULL && ret != 0)
			return (ret);
	}

	for (node = OF_child(node); node; node = OF_peer(node)) {
		if (OF_getprop(node, "reg", &reg, sizeof(reg)) < sizeof(reg))
			continue;

		b = OFW_PCI_PHYS_HI_BUS(reg.phys_hi);
		d = OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi);
		f = OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi);

		tag = PCITAG_CREATE(node, b, d, f);

		bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
		if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
			continue;

		ret = pci_probe_device(sc, tag, match, pap);
		if (match != NULL && ret != 0)
			return (ret);
	}

	return (0);
}

int
ofw_intr_map(int node, uint32_t *addr, uint32_t *intr)
{
	uint32_t imap[144], mmask[8], *mp, *mp1;
	uint32_t acells, icells, mcells;
	int ilen, mlen, i, step = 0;
	int parent;

	ilen = OF_getprop(node, "interrupt-map", imap, sizeof(imap));
	mlen = OF_getprop(node, "interrupt-map-mask", mmask, sizeof(mmask));
	if (ilen < 0 || mlen < 0)
		return (-1);

	if ((OF_getprop(node, "#address-cells", &acells, 4) < 0) ||
	    (OF_getprop(node, "#interrupt-cells", &icells, 4) < 0))
		return (-1);

	mcells = acells + icells;
	if (mcells != (mlen / sizeof(mmask[0])))
		return (-1);

	for (i = 0; i < mcells; i++)
		addr[i] &= mmask[i];

	/* interrupt-map is formatted as follows
	 * int * #address-cells, int * #interrupt-cells, int, int, int
	 * eg
	 * address-cells = 3
	 * interrupt-cells = 1
	 * 00001000 00000000 00000000 00000000 ff911258 00000034 00000001
	 * 00001800 00000000 00000000 00000000 ff911258 00000035 00000001
	 * 00002000 00000000 00000000 00000000 ff911258 00000036 00000001
	 * | address cells          | | intr | |node| | irq  | |edge/level|
	 *                            | cells|        | interrupt cells   |
	 *                                            | of node           |
	 * or at least something close to that.
	 */
	for (mp = imap; ilen > mlen; mp += step) {
		mp1 = mp + mcells;
		parent = *mp1;

		if (bcmp(mp, addr, mlen) == 0) {
			char ic[20];

			/*
			 * If we have a match and the parent is not an
			 * interrupt controller continue recursively.
			 */
			if (OF_getprop(parent, "interrupt-controller", ic, 20))
				return ofw_intr_map(parent, &mp1[1], intr);

			*intr = mp1[1];
			return (0);
		}

		if (OF_getprop(parent, "#address-cells", &acells, 4) < 0)
			acells = 0;
		if (OF_getprop(parent, "#interrupt-cells", &icells, 4) < 0)
			break;

		step = mcells + 1 + acells + icells;
		ilen -= step * sizeof(imap[0]);
	}

	return (-1);
}


code:
/*	$OpenBSD: pciide_machdep.c,v 1.4 2005/12/12 18:25:47 kettenis Exp $	*/
/*	$NetBSD: pciide_machdep.c,v 1.2 1999/02/19 18:01:27 mycroft Exp $	*/

/*
 * Copyright (c) 1998 Christopher G. Demetriou.  All rights reserved.
 *
 * 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 Christopher G. Demetriou
 *	for the NetBSD Project.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

/*
 * PCI IDE controller driver (i386 machine-dependent portion).
 *
 * Author: Christopher G. Demetriou, March 2, 1998 (derived from NetBSD
 * sys/dev/pci/ppb.c, revision 1.16).
 *
 * See "PCI IDE Controller Specification, Revision 1.0 3/4/94" from the
 * PCI SIG.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>

#include <machine/autoconf.h>

void *
pciide_machdep_compat_intr_establish(struct device *dev,
    struct pci_attach_args *pa, int chan, int (*func)(void *), void *arg)
{
	int irq;
	void *cookie;

	irq = PCIIDE_COMPAT_IRQ(chan);
	cookie = mac_intr_establish(NULL, irq, IST_EDGE, IPL_BIO,
	    func, arg, dev->dv_xname);

	return (cookie);
}

void
pciide_machdep_compat_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
{
	mac_intr_disestablish(NULL, cookie);
}


code:
/*	$OpenBSD: vgafb.c,v 1.60 2014/07/28 15:00:27 jsg Exp $	*/
/*	$NetBSD: vga.c,v 1.3 1996/12/02 22:24:54 cgd Exp $	*/

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>

#include <machine/bus.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>

#include <dev/ofw/openfirm.h>
#include <macppc/macppc/ofw_machdep.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/vga_pcivar.h>

struct vgafb_softc {
	struct device		sc_dev;
	int			sc_node;

	bus_addr_t		sc_mem_addr, sc_mmio_addr;
	bus_size_t		sc_mem_size, sc_mmio_size;

	struct rasops_info	sc_ri;
	uint8_t			sc_cmap[256 * 3];
	u_int			sc_mode;

	struct	wsscreen_descr	sc_wsd;
	struct	wsscreen_list	sc_wsl;
	struct	wsscreen_descr *sc_scrlist[1];

	int			sc_backlight_on;
};

int	vgafb_ioctl(void *, u_long, caddr_t, int, struct proc *);
paddr_t	vgafb_mmap(void *, off_t, int);
int	vgafb_alloc_screen(void *, const struct wsscreen_descr *, void **,
	    int *, int *, long *);
void	vgafb_free_screen(void *, void *);
int	vgafb_show_screen(void *, void *, int, void (*cb)(void *, int, int),
	    void *);
int	vgafb_load_font(void *, void *, struct wsdisplay_font *);
int	vgafb_list_font(void *, struct wsdisplay_font *);
void	vgafb_burn(void *v, u_int , u_int);
void	vgafb_restore_default_colors(struct vgafb_softc *);
int	vgafb_is_console(int);
int	vgafb_console_init(struct vgafb_softc *);
int	vgafb_mapregs(struct vgafb_softc *, struct pci_attach_args *);

struct wsdisplay_accessops vgafb_accessops = {
	.ioctl = vgafb_ioctl,
	.mmap = vgafb_mmap,
	.alloc_screen = vgafb_alloc_screen,
	.free_screen = vgafb_free_screen,
	.show_screen = vgafb_show_screen,
	.load_font = vgafb_load_font,
	.list_font = vgafb_list_font,
	.burn_screen = vgafb_burn
};

int	vgafb_getcmap(uint8_t *, struct wsdisplay_cmap *);
int	vgafb_putcmap(uint8_t *, struct wsdisplay_cmap *);

int	vgafb_match(struct device *, void *, void *);
void	vgafb_attach(struct device *, struct device *, void *);

const struct cfattach vgafb_ca = {
	sizeof(struct vgafb_softc), vgafb_match, vgafb_attach,
};

struct cfdriver vgafb_cd = {
	NULL, "vgafb", DV_DULL,
};

#ifdef APERTURE
extern int allowaperture;
#endif

int
vgafb_match(struct device *parent, void *match, void *aux)
{
	struct pci_attach_args *pa = aux;
	int node;

	if (DEVICE_IS_VGA_PCI(pa->pa_class) == 0) {
		/*
		 * XXX Graphic cards found in iMac G3 have a ``Misc''
		 * subclass, match them all.
		 */
		if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
		    PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_MISC)
			return (0);
	}

	/*
	 * XXX Non-console devices do not get configured by the PROM,
	 * XXX so do not attach them yet.
	 */
	node = PCITAG_NODE(pa->pa_tag);
	if (!vgafb_is_console(node))
		return (0);

	return (1);
}

void
vgafb_attach(struct device *parent, struct device *self, void *aux)
{
	struct vgafb_softc *sc = (struct vgafb_softc *)self;
	struct pci_attach_args *pa = aux;
	struct wsemuldisplaydev_attach_args waa;

	sc->sc_node = PCITAG_NODE(pa->pa_tag);

	if (vgafb_mapregs(sc, pa))
		return;

	if (vgafb_console_init(sc))
		return;

	sc->sc_scrlist[0] = &sc->sc_wsd;
	sc->sc_wsl.nscreens = 1;
	sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;

	waa.console = 1;
	waa.scrdata = &sc->sc_wsl;
	waa.accessops = &vgafb_accessops;
	waa.accesscookie = sc;
	waa.defaultscreens = 0;

	/* no need to keep the burner function if no hw support */
	if (cons_backlight_available == 0)
		vgafb_accessops.burn_screen = NULL;
	else {
		sc->sc_backlight_on = WSDISPLAYIO_VIDEO_OFF;
		vgafb_burn(sc, WSDISPLAYIO_VIDEO_ON, 0);	/* paranoia */
	}

#ifdef RAMDISK_HOOKS
	if (vga_aperture_needed(pa))
		printf("%s: aperture needed\n", sc->sc_dev.dv_xname);
#endif

	config_found(self, &waa, wsemuldisplaydevprint);
}

int
vgafb_console_init(struct vgafb_softc *sc)
{
	struct rasops_info *ri = &sc->sc_ri;
	long defattr;

	ri->ri_flg = RI_CENTER | RI_VCONS | RI_WRONLY;
	ri->ri_hw = sc;

	ofwconsswitch(ri);

	rasops_init(ri, 160, 160);

	strlcpy(sc->sc_wsd.name, "std", sizeof(sc->sc_wsd.name));
	sc->sc_wsd.capabilities = ri->ri_caps;
	sc->sc_wsd.nrows = ri->ri_rows;
	sc->sc_wsd.ncols = ri->ri_cols;
	sc->sc_wsd.textops = &ri->ri_ops;
	sc->sc_wsd.fontwidth = ri->ri_font->fontwidth;
	sc->sc_wsd.fontheight = ri->ri_font->fontheight;

	ri->ri_ops.alloc_attr(ri->ri_active, 0, 0, 0, &defattr);
	wsdisplay_cnattach(&sc->sc_wsd, ri->ri_active, ri->ri_ccol, ri->ri_crow,
	    defattr);

	return (0);
}

void
vgafb_restore_default_colors(struct vgafb_softc *sc)
{
	bcopy(rasops_cmap, sc->sc_cmap, sizeof(sc->sc_cmap));
	of_setcolors(sc->sc_cmap, 0, 256);
}

int
vgafb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
{
	struct vgafb_softc *sc = v;
	struct rasops_info *ri = &sc->sc_ri;
	struct wsdisplay_cmap *cm;
	struct wsdisplay_fbinfo *wdf;
	int rc;

	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_PCIVGA;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->width = ri->ri_width;
		wdf->height = ri->ri_height;
		wdf->depth = ri->ri_depth;
		wdf->cmsize = 256;
		break;
	case WSDISPLAYIO_LINEBYTES:
		*(uint *)data = ri->ri_stride;
		break;
	case WSDISPLAYIO_GETCMAP:
		cm = (struct wsdisplay_cmap *)data;
		rc = vgafb_getcmap(sc->sc_cmap, cm);
		if (rc != 0)
			return rc;
		break;
	case WSDISPLAYIO_PUTCMAP:
		cm = (struct wsdisplay_cmap *)data;
		rc = vgafb_putcmap(sc->sc_cmap, cm);
		if (rc != 0)
			return (rc);
		if (ri->ri_depth == 8)
			of_setcolors(sc->sc_cmap, cm->index, cm->count);
		break;
	case WSDISPLAYIO_SMODE:
		sc->sc_mode = *(u_int *)data;
		if (ri->ri_depth == 8)
			vgafb_restore_default_colors(sc);
		break;
	case WSDISPLAYIO_GETPARAM:
	{
		struct wsdisplay_param *dp = (struct wsdisplay_param *)data;

		switch (dp->param) {
		case WSDISPLAYIO_PARAM_BRIGHTNESS:
			if (cons_backlight_available != 0) {
				dp->min = MIN_BRIGHTNESS;
				dp->max = MAX_BRIGHTNESS;
				dp->curval = cons_brightness;
				return 0;
			}
			return -1;
		case WSDISPLAYIO_PARAM_BACKLIGHT:
			if (cons_backlight_available != 0) {
				dp->min = 0;
				dp->max = 1;
				dp->curval = sc->sc_backlight_on;
				return 0;
			} else
				return -1;
		}
	}
		return -1;

	case WSDISPLAYIO_SETPARAM:
	{
		struct wsdisplay_param *dp = (struct wsdisplay_param *)data;

		switch (dp->param) {
		case WSDISPLAYIO_PARAM_BRIGHTNESS:
			if (cons_backlight_available == 1) {
				of_setbrightness(dp->curval);
				return 0;
			} else
				return -1;
		case WSDISPLAYIO_PARAM_BACKLIGHT:
			if (cons_backlight_available != 0) {
				vgafb_burn(sc,
				    dp->curval ? WSDISPLAYIO_VIDEO_ON :
				      WSDISPLAYIO_VIDEO_OFF, 0);
				return 0;
			} else
				return -1;
		}
	}
		return -1;

	case WSDISPLAYIO_SVIDEO:
	case WSDISPLAYIO_GVIDEO:
		break;

	case WSDISPLAYIO_GCURPOS:
	case WSDISPLAYIO_SCURPOS:
	case WSDISPLAYIO_GCURMAX:
	case WSDISPLAYIO_GCURSOR:
	case WSDISPLAYIO_SCURSOR:
	default:
		return -1; /* not supported yet */
	}

	return (0);
}

paddr_t
vgafb_mmap(void *v, off_t off, int prot)
{
	struct vgafb_softc *sc = v;

	if (off & PGOFSET)
		return (-1);

	switch (sc->sc_mode) {
	case WSDISPLAYIO_MODE_MAPPED:
#ifdef APERTURE
		if (allowaperture == 0)
			return (-1);
#endif

		if (sc->sc_mmio_size == 0)
			return (-1);

		if (off >= sc->sc_mem_addr &&
		    off < (sc->sc_mem_addr + sc->sc_mem_size))
			return (off);

		if (off >= sc->sc_mmio_addr &&
		    off < (sc->sc_mmio_addr + sc->sc_mmio_size))
			return (off);
		break;

	case WSDISPLAYIO_MODE_DUMBFB:
		if (off >= 0x00000 && off < sc->sc_mem_size)
			return (sc->sc_mem_addr + off);
		break;

	}

	return (-1);
}

int
vgafb_is_console(int node)
{
	extern int fbnode;

	return (fbnode == node);
}

int
vgafb_getcmap(uint8_t *cmap, struct wsdisplay_cmap *cm)
{
	uint index = cm->index, count = cm->count, i;
	uint8_t ramp[256], *dst, *src;
	int rc;

	if (index >= 256 || count > 256 - index)
		return EINVAL;

	index *= 3;

	src = cmap + index;
	dst = ramp;
	for (i = 0; i < count; i++)
		*dst++ = *src, src += 3;
	rc = copyout(ramp, cm->red, count);
	if (rc != 0)
		return rc;

	src = cmap + index + 1;
	dst = ramp;
	for (i = 0; i < count; i++)
		*dst++ = *src, src += 3;
	rc = copyout(ramp, cm->green, count);
	if (rc != 0)
		return rc;

	src = cmap + index + 2;
	dst = ramp;
	for (i = 0; i < count; i++)
		*dst++ = *src, src += 3;
	rc = copyout(ramp, cm->blue, count);
	if (rc != 0)
		return rc;

	return 0;
}

int
vgafb_putcmap(uint8_t *cmap, struct wsdisplay_cmap *cm)
{
	uint index = cm->index, count = cm->count, i;
	uint8_t ramp[256], *dst, *src;
	int rc;

	if (index >= 256 || count > 256 - index)
		return EINVAL;

	index *= 3;

	rc = copyin(cm->red, ramp, count);
	if (rc != 0)
		return rc;
	dst = cmap + index;
	src = ramp;
	for (i = 0; i < count; i++)
		*dst = *src++, dst += 3;

	rc = copyin(cm->green, ramp, count);
	if (rc != 0)
		return rc;
	dst = cmap + index + 1;
	src = ramp;
	for (i = 0; i < count; i++)
		*dst = *src++, dst += 3;

	rc = copyin(cm->blue, ramp, count);
	if (rc != 0)
		return rc;
	dst = cmap + index + 2;
	src = ramp;
	for (i = 0; i < count; i++)
		*dst = *src++, dst += 3;

	return 0;
}

void
vgafb_burn(void *v, u_int on, u_int flags)
{
	struct vgafb_softc *sc = v;

	if (sc->sc_backlight_on != on) {
		of_setbacklight(on == WSDISPLAYIO_VIDEO_ON);
		sc->sc_backlight_on = on;
	}
}

int
vgafb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    int *curxp, int *curyp, long *attrp)
{
	struct vgafb_softc *sc = v;
	struct rasops_info *ri = &sc->sc_ri;

	return rasops_alloc_screen(ri, cookiep, curxp, curyp, attrp);
}

void
vgafb_free_screen(void *v, void *cookie)
{
	struct vgafb_softc *sc = v;
	struct rasops_info *ri = &sc->sc_ri;

	return rasops_free_screen(ri, cookie);
}

int
vgafb_show_screen(void *v, void *cookie, int waitok,
    void (*cb)(void *, int, int), void *cbarg)
{
	struct vgafb_softc *sc = v;
	struct rasops_info *ri = &sc->sc_ri;

	if (cookie == ri->ri_active)
		return (0);

	return rasops_show_screen(ri, cookie, waitok, cb, cbarg);
}

int
vgafb_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
{
	struct vgafb_softc *sc = v;
	struct rasops_info *ri = &sc->sc_ri;

	return rasops_load_font(ri, emulcookie, font);
}

int
vgafb_list_font(void *v, struct wsdisplay_font *font)
{
	struct vgafb_softc *sc = v;
	struct rasops_info *ri = &sc->sc_ri;

	return rasops_list_font(ri, font);
}

int
vgafb_mapregs(struct vgafb_softc *sc, struct pci_attach_args *pa)
{
	bus_addr_t ba;
	bus_size_t bs;
	int hasmem = 0, hasmmio = 0;
	uint32_t i, cf;
	int rv;

	for (i = PCI_MAPREG_START; i <= PCI_MAPREG_PPB_END; i += 4) {
		cf = pci_conf_read(pa->pa_pc, pa->pa_tag, i);
		if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_MEM) {
			/* Memory mapping... frame memory or mmio? */
			rv = pci_mem_find(pa->pa_pc, pa->pa_tag, i,
			    &ba, &bs, NULL);
			if (rv != 0)
				continue;

			if (bs == 0 /* || ba == 0 */) {
				/* ignore this entry */
			} else if (hasmem == 0) {
				/*
				 * first memory slot found goes into memory,
				 * this is for the case of no mmio
				 */
				sc->sc_mem_addr = ba;
				sc->sc_mem_size = bs;
				hasmem = 1;
			} else {
				/*
				 * Oh, we have a second `memory'
				 * region, is this region the vga memory
				 * or mmio, we guess that memory is
				 * the larger of the two.
				 */
				if (sc->sc_mem_size >= bs) {
					/* this is the mmio */
					sc->sc_mmio_addr = ba;
					sc->sc_mmio_size = bs;
					hasmmio = 1;
				} else {
					/* this is the memory */
					sc->sc_mmio_addr = sc->sc_mem_addr;
					sc->sc_mmio_size = sc->sc_mem_size;
					sc->sc_mem_addr = ba;
					sc->sc_mem_size = bs;
				}
			}
		}
	}

	/* failure to initialize io ports should not prevent attachment */
	if (hasmem == 0) {
		printf(": could not find memory space\n");
		return (1);
	}

	if (hasmmio)
		printf (", mmio");
	printf("\n");

	return (0);
}


path: sys/arch/macppc/stand/CVS/Entries


code: src/sys/arch/macppc/stand

path: sys/arch/macppc/stand/CVS/Repository