Annotation of sys/arch/sparc64/dev/ebus_mainbus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ebus_mainbus.c,v 1.3 2007/04/07 20:15:54 kettenis Exp $ */
2:
3: /*
4: * Copyright (c) 2007 Mark Kettenis
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #ifdef DEBUG
20: #define EDB_PROM 0x01
21: #define EDB_CHILD 0x02
22: #define EDB_INTRMAP 0x04
23: #define EDB_BUSMAP 0x08
24: #define EDB_BUSDMA 0x10
25: #define EDB_INTR 0x20
26: extern int ebus_debug;
27: #define DPRINTF(l, s) do { if (ebus_debug & l) printf s; } while (0)
28: #else
29: #define DPRINTF(l, s)
30: #endif
31:
32: #include <sys/param.h>
33: #include <sys/conf.h>
34: #include <sys/device.h>
35: #include <sys/errno.h>
36: #include <sys/extent.h>
37: #include <sys/malloc.h>
38: #include <sys/systm.h>
39: #include <sys/time.h>
40:
41: #define _SPARC_BUS_DMA_PRIVATE
42: #include <machine/bus.h>
43: #include <machine/autoconf.h>
44: #include <machine/openfirm.h>
45:
46: #include <dev/pci/pcivar.h>
47:
48: #include <sparc64/dev/iommureg.h>
49: #include <sparc64/dev/ebusreg.h>
50: #include <sparc64/dev/ebusvar.h>
51: #include <sparc64/dev/pyrovar.h>
52:
53: extern struct cfdriver pyro_cd;
54:
55: int ebus_mainbus_match(struct device *, void *, void *);
56: void ebus_mainbus_attach(struct device *, struct device *, void *);
57:
58: struct cfattach ebus_mainbus_ca = {
59: sizeof(struct ebus_softc), ebus_mainbus_match, ebus_mainbus_attach
60: };
61:
62:
63: int _ebus_mainbus_bus_map(bus_space_tag_t, bus_space_tag_t,
64: bus_addr_t, bus_size_t, int, bus_space_handle_t *);
65: void *_ebus_mainbus_intr_establish(bus_space_tag_t, bus_space_tag_t,
66: int, int, int, int (*)(void *), void *, const char *);
67: bus_space_tag_t ebus_alloc_bus_tag(struct ebus_softc *, bus_space_tag_t);
68:
69:
70: int
71: ebus_mainbus_match(struct device *parent, void *match, void *aux)
72: {
73: struct mainbus_attach_args *ma = aux;
74:
75: if (strcmp(ma->ma_name, "ebus") == 0)
76: return (1);
77: return (0);
78: }
79:
80: void
81: ebus_mainbus_attach(struct device *parent, struct device *self, void *aux)
82: {
83: struct ebus_softc *sc = (struct ebus_softc *)self;
84: struct mainbus_attach_args *ma = aux;
85: struct ebus_attach_args eba;
86: struct ebus_interrupt_map_mask *immp;
87: int node, nmapmask, error;
88: struct pyro_softc *psc;
89: int i;
90:
91: sc->sc_node = node = ma->ma_node;
92: sc->sc_ign = INTIGN((ma->ma_upaid) << INTMAP_IGN_SHIFT);
93:
94: printf(": ign %x", sc->sc_ign);
95:
96: for (i = 0; i < pyro_cd.cd_ndevs; i++) {
97: psc = pyro_cd.cd_devs[i];
98: if (psc && psc->sc_ign == sc->sc_ign) {
99: sc->sc_bust = psc->sc_bust;
100: sc->sc_csr = psc->sc_csr;
101: sc->sc_csrh = psc->sc_csrh;
102: break;
103: }
104: }
105:
106: if (sc->sc_csr == 0) {
107: printf(": can't find matching host bridge leaf\n");
108: return;
109: }
110:
111: printf("\n");
112:
113: sc->sc_memtag = ebus_alloc_bus_tag(sc, ma->ma_bustag);
114: sc->sc_iotag = ebus_alloc_bus_tag(sc, ma->ma_bustag);
115: sc->sc_dmatag = ebus_alloc_dma_tag(sc, ma->ma_dmatag);
116:
117: /*
118: * fill in our softc with information from the prom
119: */
120: sc->sc_intmap = NULL;
121: sc->sc_range = NULL;
122: error = getprop(node, "interrupt-map",
123: sizeof(struct ebus_interrupt_map),
124: &sc->sc_nintmap, (void **)&sc->sc_intmap);
125: switch (error) {
126: case 0:
127: immp = &sc->sc_intmapmask;
128: error = getprop(node, "interrupt-map-mask",
129: sizeof(struct ebus_interrupt_map_mask), &nmapmask,
130: (void **)&immp);
131: if (error)
132: panic("could not get ebus interrupt-map-mask");
133: if (nmapmask != 1)
134: panic("ebus interrupt-map-mask is broken");
135: break;
136: case ENOENT:
137: break;
138: default:
139: panic("ebus interrupt-map: error %d", error);
140: break;
141: }
142:
143: error = getprop(node, "ranges", sizeof(struct ebus_mainbus_ranges),
144: &sc->sc_nrange, (void **)&sc->sc_range);
145: if (error)
146: panic("ebus ranges: error %d", error);
147:
148: /*
149: * now attach all our children
150: */
151: DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node));
152: for (node = firstchild(node); node; node = nextsibling(node)) {
153: if (ebus_setup_attach_args(sc, node, &eba) != 0) {
154: DPRINTF(EDB_CHILD,
155: ("ebus_mainbus_attach: %s: incomplete\n",
156: getpropstring(node, "name")));
157: continue;
158: } else {
159: DPRINTF(EDB_CHILD, ("- found child `%s', attaching\n",
160: eba.ea_name));
161: (void)config_found(self, &eba, ebus_print);
162: }
163: ebus_destroy_attach_args(&eba);
164: }
165: }
166:
167: bus_space_tag_t
168: ebus_alloc_bus_tag(struct ebus_softc *sc, bus_space_tag_t parent)
169: {
170: struct sparc_bus_space_tag *bt;
171:
172: bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT);
173: if (bt == NULL)
174: panic("could not allocate ebus bus tag");
175:
176: bzero(bt, sizeof *bt);
177: snprintf(bt->name, sizeof(bt->name), "%s", sc->sc_dev.dv_xname);
178: bt->cookie = sc;
179: bt->parent = parent;
180: bt->asi = parent->asi;
181: bt->sasi = parent->sasi;
182: bt->sparc_bus_map = _ebus_mainbus_bus_map;
183: bt->sparc_intr_establish = _ebus_mainbus_intr_establish;
184:
185: return (bt);
186: }
187:
188: int
189: _ebus_mainbus_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset,
190: bus_size_t size, int flags, bus_space_handle_t *hp)
191: {
192: struct ebus_softc *sc = t->cookie;
193: struct ebus_mainbus_ranges *range;
194: bus_addr_t hi, lo;
195: int i;
196:
197: DPRINTF(EDB_BUSMAP,
198: ("\n_ebus_mainbus_bus_map: off %016llx sz %x flags %d",
199: (unsigned long long)offset, (int)size, (int)flags));
200:
201: if (t->parent == 0 || t->parent->sparc_bus_map == 0) {
202: printf("\n_ebus_mainbus_bus_map: invalid parent");
203: return (EINVAL);
204: }
205:
206: t = t->parent;
207:
208: if (flags & BUS_SPACE_MAP_PROMADDRESS) {
209: return ((*t->sparc_bus_map)
210: (t, t0, offset, size, flags, hp));
211: }
212:
213: hi = offset >> 32UL;
214: lo = offset & 0xffffffff;
215: range = (struct ebus_mainbus_ranges *)sc->sc_range;
216:
217: DPRINTF(EDB_BUSMAP, (" (hi %08x lo %08x)", (u_int)hi, (u_int)lo));
218: for (i = 0; i < sc->sc_nrange; i++) {
219: bus_addr_t addr;
220:
221: if (hi != range[i].child_hi)
222: continue;
223: if (lo < range[i].child_lo ||
224: (lo + size) > (range[i].child_lo + range[i].size))
225: continue;
226:
227: addr = ((bus_addr_t)range[i].phys_hi << 32UL) |
228: range[i].phys_lo;
229: addr += lo;
230: DPRINTF(EDB_BUSMAP,
231: ("\n_ebus_mainbus_bus_map: paddr offset %qx addr %qx\n",
232: (unsigned long long)offset, (unsigned long long)addr));
233: return ((*t->sparc_bus_map)(t, t0, addr, size, flags, hp));
234: }
235: DPRINTF(EDB_BUSMAP, (": FAILED\n"));
236: return (EINVAL);
237: }
238:
239: void *
240: _ebus_mainbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
241: int level, int flags, int (*handler)(void *), void *arg, const char *what)
242: {
243: struct ebus_softc *sc = t->cookie;
244: struct intrhand *ih = NULL;
245: volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL;
246: int ino;
247:
248: ihandle |= sc->sc_ign;
249: ino = INTINO(ihandle);
250:
251: if ((flags & BUS_INTR_ESTABLISH_SOFTINTR) == 0) {
252: u_int64_t *imap, *iclr;
253:
254: /* XXX */
255: imap = bus_space_vaddr(sc->sc_bust, sc->sc_csrh) + 0x1000;
256: iclr = bus_space_vaddr(sc->sc_bust, sc->sc_csrh) + 0x1400;
257: intrmapptr = &imap[ino];
258: intrclrptr = &iclr[ino];
259: ino |= INTVEC(ihandle);
260: }
261:
262: ih = bus_intr_allocate(t0, handler, arg, ino, level, intrmapptr,
263: intrclrptr, what);
264: if (ih == NULL)
265: return (NULL);
266:
267: intr_establish(ih->ih_pil, ih);
268:
269: if (intrmapptr != NULL) {
270: u_int64_t intrmap;
271:
272: intrmap = *intrmapptr;
273: intrmap |= (1LL << 6);
274: intrmap |= INTMAP_V;
275: *intrmapptr = intrmap;
276: intrmap = *intrmapptr;
277: ih->ih_number |= intrmap & INTMAP_INR;
278: }
279:
280: return (ih);
281: }
CVSweb