ofw_isa.c revision 153057
1139825Simp/*-
286232Stmm * Copyright (c) 1999, 2000 Matthew R. Green
3117119Stmm * Copyright (c) 2001, 2003 Thomas Moestl <tmm@FreeBSD.org>
486232Stmm * All rights reserved.
586232Stmm *
686232Stmm * Redistribution and use in source and binary forms, with or without
786232Stmm * modification, are permitted provided that the following conditions
886232Stmm * are met:
986232Stmm * 1. Redistributions of source code must retain the above copyright
1086232Stmm *    notice, this list of conditions and the following disclaimer.
1186232Stmm * 2. Redistributions in binary form must reproduce the above copyright
1286232Stmm *    notice, this list of conditions and the following disclaimer in the
1386232Stmm *    documentation and/or other materials provided with the distribution.
1486232Stmm * 3. The name of the author may not be used to endorse or promote products
1586232Stmm *    derived from this software without specific prior written permission.
1686232Stmm *
1786232Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1886232Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1986232Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2086232Stmm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2186232Stmm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2286232Stmm * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2386232Stmm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2486232Stmm * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2586232Stmm * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2686232Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2786232Stmm * SUCH DAMAGE.
2886232Stmm *
2986232Stmm *	from: NetBSD: ebus.c,v 1.26 2001/09/10 16:27:53 eeh Exp
3086232Stmm */
3186232Stmm
32153057Smarius#include <sys/cdefs.h>
33153057Smarius__FBSDID("$FreeBSD: head/sys/sparc64/isa/ofw_isa.c 153057 2005-12-03 18:11:26Z marius $");
34153057Smarius
3586232Stmm/*
3686232Stmm * Helper functions which can be used in both ISA and EBus code.
3786232Stmm */
3886232Stmm
3986232Stmm#include <sys/param.h>
4091966Stmm#include <sys/systm.h>
4186232Stmm#include <sys/bus.h>
4286232Stmm
43119338Simp#include <dev/ofw/openfirm.h>
4486232Stmm
45117119Stmm#include <machine/bus.h>
4686232Stmm#include <machine/resource.h>
4786232Stmm#include <machine/ofw_bus.h>
4886232Stmm
49117119Stmm#include <sparc64/pci/ofw_pci.h>
5086232Stmm#include <sparc64/isa/ofw_isa.h>
5186232Stmm
52117119Stmm#include "pcib_if.h"
53117119Stmm
54128712Stmmint
55128712Stmmofw_isa_range_restype(struct isa_ranges *range)
56128712Stmm{
57128712Stmm	int ps = ISA_RANGE_PS(range);
58128712Stmm
59128712Stmm	switch (ps) {
60128712Stmm	case PCI_CS_IO:
61128712Stmm		return (SYS_RES_IOPORT);
62128712Stmm	case PCI_CS_MEM32:
63128712Stmm		return (SYS_RES_MEMORY);
64128712Stmm	default:
65128712Stmm		panic("ofw_isa_range_restype: illegal space %x", ps);
66128712Stmm	}
67128712Stmm
68128712Stmm}
69128712Stmm
7086232Stmm/* XXX: this only supports PCI as parent bus right now. */
7186232Stmmint
72128712Stmmofw_isa_range_map(struct isa_ranges *range, int nrange, u_long *start,
73128712Stmm    u_long *end, int *which)
7486232Stmm{
75128712Stmm	struct isa_ranges *r;
76153057Smarius	uint64_t offs, cstart, cend;
7786232Stmm	int i;
7886232Stmm
7986232Stmm	for (i = 0; i < nrange; i++) {
80128712Stmm		r = &range[i];
81128712Stmm		cstart = ISA_RANGE_CHILD(r);
82128712Stmm		cend = cstart + r->size;
8386232Stmm		if (*start < cstart || *start > cend)
8486232Stmm			continue;
8586232Stmm		if (*end < cstart || *end > cend) {
8686232Stmm			panic("ofw_isa_map_iorange: iorange crosses pci "
8786232Stmm			    "ranges (%#lx not in %#lx - %#lx)", *end, cstart,
8886232Stmm			    cend);
8986232Stmm		}
90128712Stmm		offs = ISA_RANGE_PHYS(r);
9186232Stmm		*start = *start + offs - cstart;
9286232Stmm		*end  = *end + offs - cstart;
93128712Stmm		if (which != NULL)
94128712Stmm			*which = i;
95128712Stmm		return (ofw_isa_range_restype(r));
9686232Stmm	}
9786232Stmm	panic("ofw_isa_map_iorange: could not map range %#lx - %#lx",
9886232Stmm	    *start, *end);
9986232Stmm}
100117119Stmm
101117119Stmmofw_pci_intr_t
102117119Stmmofw_isa_route_intr(device_t bridge, phandle_t node, struct ofw_bus_iinfo *ii,
103117119Stmm    ofw_isa_intr_t intr)
104117119Stmm{
105117119Stmm	struct isa_regs reg;
106153057Smarius	uint8_t maskbuf[sizeof(reg) + sizeof(intr)];
107117119Stmm	device_t pbridge;
108117119Stmm	ofw_isa_intr_t mintr;
109117119Stmm
110117119Stmm	pbridge = device_get_parent(device_get_parent(bridge));
111117119Stmm	/*
112117119Stmm	 * If we get a match from using the map, the resulting INO is
113117119Stmm	 * fully specified, so we may not continue to map.
114117119Stmm	 */
115117119Stmm	if (!ofw_bus_lookup_imap(node, ii, &reg, sizeof(reg),
116117119Stmm	    &intr, sizeof(intr), &mintr, sizeof(mintr), maskbuf)) {
117117119Stmm		/* Try routing at the parent bridge. */
118117119Stmm		mintr = PCIB_ROUTE_INTERRUPT(pbridge, bridge, intr);
119117119Stmm	}
120117119Stmm	return (mintr);
121117119Stmm}
122