xref: /openbsd/sys/arch/sparc64/dev/schizo.c (revision 8a1e8cca)
1 /*	$OpenBSD: schizo.c,v 1.70 2024/03/29 21:29:33 miod Exp $	*/
2 
3 /*
4  * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
5  * Copyright (c) 2003 Henric Jungheim
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <sys/param.h>
31 #include <sys/device.h>
32 #include <sys/errno.h>
33 #include <sys/extent.h>
34 #include <sys/malloc.h>
35 #include <sys/systm.h>
36 #include <sys/time.h>
37 #include <sys/reboot.h>
38 
39 #define _SPARC_BUS_DMA_PRIVATE
40 #include <machine/bus.h>
41 #include <machine/autoconf.h>
42 #include <machine/psl.h>
43 
44 #ifdef DDB
45 #include <machine/db_machdep.h>
46 #endif
47 
48 #include <dev/pci/pcivar.h>
49 #include <dev/pci/pcireg.h>
50 
51 #include <sparc64/dev/iommureg.h>
52 #include <sparc64/dev/iommuvar.h>
53 #include <sparc64/dev/schizoreg.h>
54 #include <sparc64/dev/schizovar.h>
55 #include <sparc64/sparc64/cache.h>
56 
57 #ifdef DEBUG
58 #define SDB_PROM        0x01
59 #define SDB_BUSMAP      0x02
60 #define SDB_INTR        0x04
61 #define SDB_CONF        0x08
62 int schizo_debug = ~0;
63 #define DPRINTF(l, s)   do { if (schizo_debug & l) printf s; } while (0)
64 #else
65 #define DPRINTF(l, s)
66 #endif
67 
68 extern struct sparc_pci_chipset _sparc_pci_chipset;
69 
70 int schizo_match(struct device *, void *, void *);
71 void schizo_attach(struct device *, struct device *, void *);
72 void schizo_init(struct schizo_softc *, int);
73 void schizo_init_iommu(struct schizo_softc *, struct schizo_pbm *);
74 int schizo_print(void *, const char *);
75 
76 void schizo_set_intr(struct schizo_softc *, struct schizo_pbm *, int,
77     int (*handler)(void *), void *, int, char *);
78 int schizo_ue(void *);
79 int schizo_ce(void *);
80 int schizo_safari_error(void *);
81 int schizo_pci_error(void *);
82 
83 pci_chipset_tag_t schizo_alloc_chipset(struct schizo_pbm *, int,
84     pci_chipset_tag_t);
85 bus_space_tag_t schizo_alloc_mem_tag(struct schizo_pbm *);
86 bus_space_tag_t schizo_alloc_io_tag(struct schizo_pbm *);
87 bus_space_tag_t schizo_alloc_config_tag(struct schizo_pbm *);
88 bus_space_tag_t schizo_alloc_bus_tag(struct schizo_pbm *, const char *,
89     int, int, int);
90 bus_dma_tag_t schizo_alloc_dma_tag(struct schizo_pbm *);
91 
92 int schizo_conf_size(pci_chipset_tag_t, pcitag_t);
93 pcireg_t schizo_conf_read(pci_chipset_tag_t, pcitag_t, int);
94 void schizo_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t);
95 
96 int schizo_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
97 int schizo_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t,
98     bus_size_t, int, bus_space_handle_t *);
99 paddr_t schizo_bus_mmap(bus_space_tag_t, bus_space_tag_t, bus_addr_t, off_t,
100     int, int);
101 bus_addr_t schizo_bus_addr(bus_space_tag_t, bus_space_tag_t,
102     bus_space_handle_t);
103 void *schizo_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int,
104     int (*)(void *), void *, const char *);
105 
106 int schizo_dmamap_create(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, int,
107     bus_size_t, bus_size_t, int, bus_dmamap_t *);
108 
109 #ifdef DDB
110 void schizo_xir(void *, int);
111 #endif
112 
113 int
schizo_match(struct device * parent,void * match,void * aux)114 schizo_match(struct device *parent, void *match, void *aux)
115 {
116 	struct mainbus_attach_args *ma = aux;
117 	char *str;
118 
119 	if (strcmp(ma->ma_name, "pci") != 0)
120 		return (0);
121 
122 	str = getpropstring(ma->ma_node, "model");
123 	if (strcmp(str, "schizo") == 0)
124 		return (1);
125 
126 	str = getpropstring(ma->ma_node, "compatible");
127 	if (strcmp(str, "pci108e,8001") == 0)
128 		return (1);
129 	if (strcmp(str, "pci108e,8002") == 0)		/* XMITS */
130 		return (1);
131 	if (strcmp(str, "pci108e,a801") == 0)		/* Tomatillo */
132 		return (1);
133 
134 	return (0);
135 }
136 
137 void
schizo_attach(struct device * parent,struct device * self,void * aux)138 schizo_attach(struct device *parent, struct device *self, void *aux)
139 {
140 	struct schizo_softc *sc = (struct schizo_softc *)self;
141 	struct mainbus_attach_args *ma = aux;
142 	int busa;
143 	char *str;
144 
145 	str = getpropstring(ma->ma_node, "compatible");
146 	if (strcmp(str, "pci108e,a801") == 0)
147 		sc->sc_tomatillo = 1;
148 
149 	sc->sc_node = ma->ma_node;
150 	sc->sc_dmat = ma->ma_dmatag;
151 	sc->sc_bust = ma->ma_bustag;
152 	sc->sc_ctrl = ma->ma_reg[1].ur_paddr - 0x10000UL;
153 	sc->sc_ign = INTIGN(ma->ma_upaid << INTMAP_IGN_SHIFT);
154 
155 	if ((ma->ma_reg[0].ur_paddr & 0x00700000) == 0x00600000)
156 		busa = 1;
157 	else
158 		busa = 0;
159 
160 	if (bus_space_map(sc->sc_bust, sc->sc_ctrl,
161 	    sizeof(struct schizo_regs), 0, &sc->sc_ctrlh)) {
162 		printf(": failed to map registers\n");
163 		return;
164 	}
165 
166 	/* enable schizo ecc error interrupts */
167 	schizo_write(sc, SCZ_ECCCTRL, schizo_read(sc, SCZ_ECCCTRL) |
168 	    SCZ_ECCCTRL_EE_INTEN | SCZ_ECCCTRL_UE_INTEN |
169 	    SCZ_ECCCTRL_CE_INTEN);
170 
171 	schizo_init(sc, busa);
172 }
173 
174 void
schizo_init(struct schizo_softc * sc,int busa)175 schizo_init(struct schizo_softc *sc, int busa)
176 {
177 	struct schizo_pbm *pbm;
178 	struct pcibus_attach_args pba;
179 	int *busranges = NULL, nranges;
180 	u_int64_t match, reg;
181 
182 	pbm = malloc(sizeof(*pbm), M_DEVBUF, M_NOWAIT | M_ZERO);
183 	if (pbm == NULL)
184 		panic("schizo: can't alloc schizo pbm");
185 
186 	pbm->sp_sc = sc;
187 	pbm->sp_bus_a = busa;
188 	pbm->sp_regt = sc->sc_bust;
189 
190 	if (getprop(sc->sc_node, "ranges", sizeof(struct schizo_range),
191 	    &pbm->sp_nrange, (void **)&pbm->sp_range))
192 		panic("schizo: can't get ranges");
193 
194 	if (getprop(sc->sc_node, "bus-range", sizeof(int), &nranges,
195 	    (void **)&busranges))
196 		panic("schizo: can't get bus-range");
197 
198 	printf(": \"%s\", version %d, ign %x, bus %c %d to %d\n",
199 	    sc->sc_tomatillo ? "Tomatillo" : "Schizo",
200 	    getpropint(sc->sc_node, "version#", 0), sc->sc_ign,
201 	    busa ? 'A' : 'B', busranges[0], busranges[1]);
202 
203 	if (bus_space_subregion(pbm->sp_regt, sc->sc_ctrlh,
204 	    busa ? offsetof(struct schizo_regs, pbm_a) :
205 	    offsetof(struct schizo_regs, pbm_b),
206 	    sizeof(struct schizo_pbm_regs),
207 	    &pbm->sp_regh)) {
208 		panic("schizo: unable to create PBM handle");
209 	}
210 
211 	printf("%s: ", sc->sc_dv.dv_xname);
212 	schizo_init_iommu(sc, pbm);
213 
214 	match = schizo_read(sc, busa ? SCZ_PCIA_IO_MATCH : SCZ_PCIB_IO_MATCH);
215 	pbm->sp_confpaddr = match & ~0x8000000000000000UL;
216 
217 	pbm->sp_memt = schizo_alloc_mem_tag(pbm);
218 	pbm->sp_iot = schizo_alloc_io_tag(pbm);
219 	pbm->sp_cfgt = schizo_alloc_config_tag(pbm);
220 	pbm->sp_dmat = schizo_alloc_dma_tag(pbm);
221 
222 	if (bus_space_map(pbm->sp_cfgt, 0, 0x1000000, 0, &pbm->sp_cfgh))
223 		panic("schizo: can't map config space");
224 
225 	pbm->sp_pc = schizo_alloc_chipset(pbm, sc->sc_node,
226 	    &_sparc_pci_chipset);
227 
228 	pbm->sp_pc->bustag = pbm->sp_cfgt;
229 	pbm->sp_pc->bushandle = pbm->sp_cfgh;
230 
231 	bzero(&pba, sizeof(pba));
232 	pba.pba_busname = "pci";
233 	pba.pba_domain = pci_ndomains++;
234 	pba.pba_bus = busranges[0];
235 	pba.pba_pc = pbm->sp_pc;
236 #if 0
237 	pba.pba_flags = pbm->sp_flags;
238 #endif
239 	pba.pba_dmat = pbm->sp_dmat;
240 	pba.pba_memt = pbm->sp_memt;
241 	pba.pba_iot = pbm->sp_iot;
242 	pba.pba_pc->conf_size = schizo_conf_size;
243 	pba.pba_pc->conf_read = schizo_conf_read;
244 	pba.pba_pc->conf_write = schizo_conf_write;
245 	pba.pba_pc->intr_map = schizo_intr_map;
246 
247 	free(busranges, M_DEVBUF, 0);
248 
249 	schizo_pbm_write(pbm, SCZ_PCI_INTR_RETRY, 5);
250 
251 	/* clear out the bus errors */
252 	schizo_pbm_write(pbm, SCZ_PCI_CTRL, schizo_pbm_read(pbm, SCZ_PCI_CTRL));
253 	schizo_pbm_write(pbm, SCZ_PCI_AFSR, schizo_pbm_read(pbm, SCZ_PCI_AFSR));
254 	schizo_cfg_write(pbm, PCI_COMMAND_STATUS_REG,
255 	    schizo_cfg_read(pbm, PCI_COMMAND_STATUS_REG));
256 
257 	reg = schizo_pbm_read(pbm, SCZ_PCI_CTRL);
258 	/* enable/disable error interrupts and arbiter */
259 	reg |= SCZ_PCICTRL_EEN | SCZ_PCICTRL_MMU_INT | SCZ_PCICTRL_ARB;
260 	reg &= ~SCZ_PCICTRL_SBH_INT;
261 	schizo_pbm_write(pbm, SCZ_PCI_CTRL, reg);
262 
263 	reg = schizo_pbm_read(pbm, SCZ_PCI_DIAG);
264 	reg &= ~(SCZ_PCIDIAG_D_RTRYARB | SCZ_PCIDIAG_D_RETRY |
265 	    SCZ_PCIDIAG_D_INTSYNC);
266 	schizo_pbm_write(pbm, SCZ_PCI_DIAG, reg);
267 
268 	if (busa)
269 		schizo_set_intr(sc, pbm, PIL_HIGH, schizo_pci_error,
270 		   pbm, SCZ_PCIERR_A_INO, "pci_a");
271 	else
272 		schizo_set_intr(sc, pbm, PIL_HIGH, schizo_pci_error,
273 		   pbm, SCZ_PCIERR_B_INO, "pci_b");
274 
275 	/* double mapped */
276 	schizo_set_intr(sc, pbm, PIL_HIGH, schizo_ue, sc, SCZ_UE_INO,
277 	    "ue");
278 	schizo_set_intr(sc, pbm, PIL_HIGH, schizo_ce, sc, SCZ_CE_INO,
279 	    "ce");
280 	schizo_set_intr(sc, pbm, PIL_HIGH, schizo_safari_error, sc,
281 	    SCZ_SERR_INO, "safari");
282 
283 #ifdef DDB
284 	/*
285 	 * Only a master Tomatillo (the one with JPID[0:2] = 6)
286 	 * can/should generate XIR.
287 	 */
288 	if (sc->sc_tomatillo &&
289 	    ((schizo_read(sc, SCZ_CONTROL_STATUS) >> 20) & 0x7) == 6)
290 		db_register_xir(schizo_xir, sc);
291 #endif
292 
293 	config_found(&sc->sc_dv, &pba, schizo_print);
294 }
295 
296 int
schizo_ue(void * vsc)297 schizo_ue(void *vsc)
298 {
299 	struct schizo_softc *sc = vsc;
300 
301 	panic("%s: uncorrectable error", sc->sc_dv.dv_xname);
302 	return (1);
303 }
304 
305 int
schizo_ce(void * vsc)306 schizo_ce(void *vsc)
307 {
308 	struct schizo_softc *sc = vsc;
309 
310 	panic("%s: correctable error", sc->sc_dv.dv_xname);
311 	return (1);
312 }
313 
314 int
schizo_pci_error(void * vpbm)315 schizo_pci_error(void *vpbm)
316 {
317 	struct schizo_pbm *sp = vpbm;
318 	struct schizo_softc *sc = sp->sp_sc;
319 	u_int64_t afsr, afar, ctrl;
320 	u_int32_t csr;
321 
322 	afsr = schizo_pbm_read(sp, SCZ_PCI_AFSR);
323 	afar = schizo_pbm_read(sp, SCZ_PCI_AFAR);
324 	ctrl = schizo_pbm_read(sp, SCZ_PCI_CTRL);
325 	csr = schizo_cfg_read(sp, PCI_COMMAND_STATUS_REG);
326 
327 	printf("%s: pci bus %c error\n", sc->sc_dv.dv_xname,
328 	    sp->sp_bus_a ? 'A' : 'B');
329 
330 	printf("PCIAFSR=%llb\n", afsr, SCZ_PCIAFSR_BITS);
331 	printf("PCIAFAR=%llx\n", afar);
332 	printf("PCICTRL=%llb\n", ctrl, SCZ_PCICTRL_BITS);
333 	printf("PCICSR=%b\n", csr, PCI_COMMAND_STATUS_BITS);
334 
335 	if (ctrl & SCZ_PCICTRL_MMU_ERR) {
336 		u_int64_t ctrl, tfar;
337 
338 		ctrl = schizo_pbm_read(sp, SCZ_PCI_IOMMU_CTRL);
339 		printf("IOMMUCTRL=%llx\n", ctrl);
340 
341 		if ((ctrl & TOM_IOMMU_ERR) == 0)
342 			goto clear_error;
343 
344 		if (sc->sc_tomatillo) {
345 			tfar = schizo_pbm_read(sp, TOM_PCI_IOMMU_TFAR);
346 			printf("IOMMUTFAR=%llx\n", tfar);
347 		}
348 
349 		/* These are non-fatal if target abort was signalled. */
350 		if ((ctrl & TOM_IOMMU_ERR_MASK) == TOM_IOMMU_INV_ERR ||
351 		    ctrl & TOM_IOMMU_ILLTSBTBW_ERR ||
352 		    ctrl & TOM_IOMMU_BADVA_ERR) {
353 			if (csr & PCI_STATUS_TARGET_TARGET_ABORT) {
354 				schizo_pbm_write(sp, SCZ_PCI_IOMMU_CTRL, ctrl);
355 				goto clear_error;
356 			}
357 		}
358 	}
359 
360 	panic("%s: fatal", sc->sc_dv.dv_xname);
361 
362  clear_error:
363 	schizo_cfg_write(sp, PCI_COMMAND_STATUS_REG, csr);
364 	schizo_pbm_write(sp, SCZ_PCI_CTRL, ctrl);
365 	schizo_pbm_write(sp, SCZ_PCI_AFSR, afsr);
366 	return (1);
367 }
368 
369 int
schizo_safari_error(void * vsc)370 schizo_safari_error(void *vsc)
371 {
372 	struct schizo_softc *sc = vsc;
373 
374 	printf("%s: safari error\n", sc->sc_dv.dv_xname);
375 
376 	printf("ERRLOG=%llx\n", schizo_read(sc, SCZ_SAFARI_ERRLOG));
377 	printf("UE_AFSR=%llx\n", schizo_read(sc, SCZ_UE_AFSR));
378 	printf("UE_AFAR=%llx\n", schizo_read(sc, SCZ_UE_AFAR));
379 	printf("CE_AFSR=%llx\n", schizo_read(sc, SCZ_CE_AFSR));
380 	printf("CE_AFAR=%llx\n", schizo_read(sc, SCZ_CE_AFAR));
381 
382 	panic("%s: fatal", sc->sc_dv.dv_xname);
383 	return (1);
384 }
385 
386 void
schizo_init_iommu(struct schizo_softc * sc,struct schizo_pbm * pbm)387 schizo_init_iommu(struct schizo_softc *sc, struct schizo_pbm *pbm)
388 {
389 	struct iommu_state *is = &pbm->sp_is;
390 	int *vdma = NULL, nitem, tsbsize = 7;
391 	u_int32_t iobase = -1;
392 	vaddr_t va;
393 	char *name;
394 
395 	va = (vaddr_t)pbm->sp_flush[0x40];
396 
397 	is->is_bustag = pbm->sp_regt;
398 
399 	if (bus_space_subregion(is->is_bustag, pbm->sp_regh,
400 	    offsetof(struct schizo_pbm_regs, iommu),
401 	    sizeof(struct iommureg), &is->is_iommu)) {
402 		panic("schizo: unable to create iommu handle");
403 	}
404 
405 	is->is_sb[0] = &pbm->sp_sb;
406 	is->is_sb[0]->sb_bustag = is->is_bustag;
407 	is->is_sb[0]->sb_flush = (void *)(va & ~0x3f);
408 
409 	if (bus_space_subregion(is->is_bustag, pbm->sp_regh,
410 	    offsetof(struct schizo_pbm_regs, strbuf),
411 	    sizeof(struct iommu_strbuf), &is->is_sb[0]->sb_sb)) {
412 		panic("schizo: unable to create streaming buffer handle");
413 		is->is_sb[0]->sb_flush = NULL;
414 	}
415 
416 #if 1
417 	/* XXX disable the streaming buffers for now */
418 	bus_space_write_8(is->is_bustag, is->is_sb[0]->sb_sb,
419 	    STRBUFREG(strbuf_ctl),
420 	    bus_space_read_8(is->is_bustag, is->is_sb[0]->sb_sb,
421 		STRBUFREG(strbuf_ctl)) & ~STRBUF_EN);
422 	is->is_sb[0]->sb_flush = NULL;
423 #endif
424 
425 	name = (char *)malloc(32, M_DEVBUF, M_NOWAIT);
426 	if (name == NULL)
427 		panic("couldn't malloc iommu name");
428 	snprintf(name, 32, "%s dvma", sc->sc_dv.dv_xname);
429 
430 	/*
431 	 * Separate the men from the boys.  If the `virtual-dma'
432 	 * property exists, use it.
433 	 */
434 	if (!getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem,
435 	    (void **)&vdma)) {
436 		/* Damn.  Gotta use these values. */
437 		iobase = vdma[0];
438 #define	TSBCASE(x)	case 1 << ((x) + 23): tsbsize = (x); break
439 		switch (vdma[1]) {
440 			TSBCASE(1); TSBCASE(2); TSBCASE(3);
441 			TSBCASE(4); TSBCASE(5); TSBCASE(6);
442 		default:
443 			printf("bogus tsb size %x, using 7\n", vdma[1]);
444 			TSBCASE(7);
445 		}
446 #undef TSBCASE
447 		DPRINTF(SDB_BUSMAP, ("schizo_iommu_init: iobase=0x%x\n", iobase));
448 		free(vdma, M_DEVBUF, 0);
449 	} else {
450 		DPRINTF(SDB_BUSMAP, ("schizo_iommu_init: getprop failed, "
451 		    "using iobase=0x%x, tsbsize=%d\n", iobase, tsbsize));
452 	}
453 
454 	iommu_init(name, &iommu_hw_default, is, tsbsize, iobase);
455 }
456 
457 int
schizo_print(void * aux,const char * p)458 schizo_print(void *aux, const char *p)
459 {
460 	if (p == NULL)
461 		return (UNCONF);
462 	return (QUIET);
463 }
464 
465 int
schizo_conf_size(pci_chipset_tag_t pc,pcitag_t tag)466 schizo_conf_size(pci_chipset_tag_t pc, pcitag_t tag)
467 {
468 	return PCI_CONFIG_SPACE_SIZE;
469 }
470 
471 pcireg_t
schizo_conf_read(pci_chipset_tag_t pc,pcitag_t tag,int reg)472 schizo_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
473 {
474 	struct cpu_info *ci = curcpu();
475 	pcireg_t val;
476 	int s;
477 
478 	s = splhigh();
479 	__membar("#Sync");
480 	ci->ci_pci_probe = 1;
481 	val = bus_space_read_4(pc->bustag, pc->bushandle,
482 	    PCITAG_OFFSET(tag) + reg);
483 	__membar("#Sync");
484 	if (ci->ci_pci_fault)
485 		val = 0xffffffff;
486 	ci->ci_pci_probe = ci->ci_pci_fault = 0;
487 	splx(s);
488 
489 	return (val);
490 }
491 
492 void
schizo_conf_write(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t data)493 schizo_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
494 {
495         bus_space_write_4(pc->bustag, pc->bushandle,
496 	    PCITAG_OFFSET(tag) + reg, data);
497 }
498 
499 /*
500  * Bus-specific interrupt mapping
501  */
502 int
schizo_intr_map(struct pci_attach_args * pa,pci_intr_handle_t * ihp)503 schizo_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
504 {
505 	struct schizo_pbm *sp = pa->pa_pc->cookie;
506 	struct schizo_softc *sc = sp->sp_sc;
507 	u_int dev;
508 
509 	if (*ihp != (pci_intr_handle_t)-1) {
510 		*ihp |= sc->sc_ign;
511 		return (0);
512 	}
513 
514 	/*
515 	 * We didn't find a PROM mapping for this interrupt.  Try to
516 	 * construct one ourselves based on the swizzled interrupt pin
517 	 * and the interrupt mapping for PCI slots documented in the
518 	 * UltraSPARC-IIi User's Manual.
519 	 */
520 
521 	if (pa->pa_intrpin == 0)
522 		return (-1);
523 
524 	/*
525 	 * This deserves some documentation.  Should anyone
526 	 * have anything official looking, please speak up.
527 	 */
528 	dev = pa->pa_device - 1;
529 
530 	*ihp = (pa->pa_intrpin - 1) & INTMAP_PCIINT;
531 	*ihp |= (dev << 2) & INTMAP_PCISLOT;
532 	*ihp |= sc->sc_ign;
533 
534 	return (0);
535 }
536 
537 void
schizo_set_intr(struct schizo_softc * sc,struct schizo_pbm * pbm,int ipl,int (* handler)(void *),void * arg,int ino,char * what)538 schizo_set_intr(struct schizo_softc *sc, struct schizo_pbm *pbm, int ipl,
539     int (*handler)(void *), void *arg, int ino, char *what)
540 {
541 	struct intrhand *ih;
542 	volatile u_int64_t *map, *clr;
543 	struct schizo_pbm_regs *pbmreg;
544 	char *name;
545 	int nlen;
546 
547 	pbmreg = bus_space_vaddr(pbm->sp_regt, pbm->sp_regh);
548 	map = &pbmreg->imap[ino];
549 	clr = &pbmreg->iclr[ino];
550 	ino |= sc->sc_ign;
551 
552 	nlen = strlen(sc->sc_dv.dv_xname) + 1 + strlen(what) + 1;
553 	name = malloc(nlen, M_DEVBUF, M_WAITOK);
554 	snprintf(name, nlen, "%s:%s", sc->sc_dv.dv_xname, what);
555 
556 	ih = bus_intr_allocate(pbm->sp_regt, handler, arg, ino, ipl,
557 	    map, clr, name);
558 	if (ih == NULL) {
559 		printf("set_intr failed...\n");
560 		free(name, M_DEVBUF, 0);
561 		return;
562 	}
563 
564 	intr_establish(ih);
565 }
566 
567 bus_space_tag_t
schizo_alloc_mem_tag(struct schizo_pbm * sp)568 schizo_alloc_mem_tag(struct schizo_pbm *sp)
569 {
570 	return (schizo_alloc_bus_tag(sp, "mem",
571 	    0x02,       /* 32-bit mem space (where's the #define???) */
572 	    ASI_PRIMARY, ASI_PRIMARY_LITTLE));
573 }
574 
575 bus_space_tag_t
schizo_alloc_io_tag(struct schizo_pbm * sp)576 schizo_alloc_io_tag(struct schizo_pbm *sp)
577 {
578 	return (schizo_alloc_bus_tag(sp, "io",
579 	    0x01,       /* IO space (where's the #define???) */
580 	    ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED));
581 }
582 
583 bus_space_tag_t
schizo_alloc_config_tag(struct schizo_pbm * sp)584 schizo_alloc_config_tag(struct schizo_pbm *sp)
585 {
586 	return (schizo_alloc_bus_tag(sp, "cfg",
587 	    0x00,       /* Config space (where's the #define???) */
588 	    ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED));
589 }
590 
591 bus_space_tag_t
schizo_alloc_bus_tag(struct schizo_pbm * pbm,const char * name,int ss,int asi,int sasi)592 schizo_alloc_bus_tag(struct schizo_pbm *pbm, const char *name, int ss,
593     int asi, int sasi)
594 {
595 	struct schizo_softc *sc = pbm->sp_sc;
596 	struct sparc_bus_space_tag *bt;
597 
598 	bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO);
599 	if (bt == NULL)
600 		panic("schizo: could not allocate bus tag");
601 
602 	snprintf(bt->name, sizeof(bt->name), "%s-pbm_%s(%d/%2.2x)",
603 	    sc->sc_dv.dv_xname, name, ss, asi);
604 
605 	bt->cookie = pbm;
606 	bt->parent = sc->sc_bust;
607 	bt->default_type = ss;
608 	bt->asi = asi;
609 	bt->sasi = sasi;
610 	bt->sparc_bus_map = schizo_bus_map;
611 	bt->sparc_bus_mmap = schizo_bus_mmap;
612 	bt->sparc_bus_addr = schizo_bus_addr;
613 	bt->sparc_intr_establish = schizo_intr_establish;
614 	return (bt);
615 }
616 
617 bus_dma_tag_t
schizo_alloc_dma_tag(struct schizo_pbm * pbm)618 schizo_alloc_dma_tag(struct schizo_pbm *pbm)
619 {
620 	struct schizo_softc *sc = pbm->sp_sc;
621 	bus_dma_tag_t dt, pdt = sc->sc_dmat;
622 
623 	dt = malloc(sizeof(*dt), M_DEVBUF, M_NOWAIT | M_ZERO);
624 	if (dt == NULL)
625 		panic("schizo: could not alloc dma tag");
626 
627 	dt->_cookie = pbm;
628 	dt->_parent = pdt;
629 	dt->_dmamap_create	= schizo_dmamap_create;
630 	dt->_dmamap_destroy	= iommu_dvmamap_destroy;
631 	dt->_dmamap_load	= iommu_dvmamap_load;
632 	dt->_dmamap_load_raw	= iommu_dvmamap_load_raw;
633 	dt->_dmamap_unload	= iommu_dvmamap_unload;
634 	dt->_dmamap_sync	= iommu_dvmamap_sync;
635 	dt->_dmamem_alloc	= iommu_dvmamem_alloc;
636 	dt->_dmamem_free	= iommu_dvmamem_free;
637 	return (dt);
638 }
639 
640 pci_chipset_tag_t
schizo_alloc_chipset(struct schizo_pbm * pbm,int node,pci_chipset_tag_t pc)641 schizo_alloc_chipset(struct schizo_pbm *pbm, int node, pci_chipset_tag_t pc)
642 {
643 	pci_chipset_tag_t npc;
644 
645 	npc = malloc(sizeof *npc, M_DEVBUF, M_NOWAIT);
646 	if (npc == NULL)
647 		panic("schizo: could not allocate pci_chipset_tag_t");
648 	memcpy(npc, pc, sizeof *pc);
649 	npc->cookie = pbm;
650 	npc->rootnode = node;
651 	return (npc);
652 }
653 
654 int
schizo_dmamap_create(bus_dma_tag_t t,bus_dma_tag_t t0,bus_size_t size,int nsegments,bus_size_t maxsegsz,bus_size_t boundary,int flags,bus_dmamap_t * dmamp)655 schizo_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size,
656     int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags,
657     bus_dmamap_t *dmamp)
658 {
659 	struct schizo_pbm *sp = t->_cookie;
660 
661 	return (iommu_dvmamap_create(t, t0, &sp->sp_sb, size, nsegments,
662 	    maxsegsz, boundary, flags, dmamp));
663 }
664 
665 int
schizo_bus_map(bus_space_tag_t t,bus_space_tag_t t0,bus_addr_t offset,bus_size_t size,int flags,bus_space_handle_t * hp)666 schizo_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset,
667     bus_size_t size, int flags, bus_space_handle_t *hp)
668 {
669 	struct schizo_pbm *pbm = t->cookie;
670 	int i, ss;
671 
672 	DPRINTF(SDB_BUSMAP,("schizo_bus_map: type %d off %llx sz %llx flags %d",
673 	    t->default_type,
674 	    (unsigned long long)offset,
675 	    (unsigned long long)size,
676 	    flags));
677 
678 	ss = t->default_type;
679 	DPRINTF(SDB_BUSMAP, (" cspace %d", ss));
680 
681 	if (t->parent == 0 || t->parent->sparc_bus_map == 0) {
682 		printf("\nschizo_bus_map: invalid parent");
683 		return (EINVAL);
684 	}
685 
686 	if (flags & BUS_SPACE_MAP_PROMADDRESS) {
687 		return ((*t->parent->sparc_bus_map)
688 		    (t, t0, offset, size, flags, hp));
689 	}
690 
691 	for (i = 0; i < pbm->sp_nrange; i++) {
692 		bus_addr_t paddr;
693 
694 		if (((pbm->sp_range[i].cspace >> 24) & 0x03) != ss)
695 			continue;
696 
697 		paddr = pbm->sp_range[i].phys_lo + offset;
698 		paddr |= ((bus_addr_t)pbm->sp_range[i].phys_hi) << 32;
699 		return ((*t->parent->sparc_bus_map)
700 		    (t, t0, paddr, size, flags, hp));
701 	}
702 
703 	return (EINVAL);
704 }
705 
706 paddr_t
schizo_bus_mmap(bus_space_tag_t t,bus_space_tag_t t0,bus_addr_t paddr,off_t off,int prot,int flags)707 schizo_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr,
708     off_t off, int prot, int flags)
709 {
710 	bus_addr_t offset = paddr;
711 	struct schizo_pbm *pbm = t->cookie;
712 	int i, ss;
713 
714 	ss = t->default_type;
715 
716 	DPRINTF(SDB_BUSMAP, ("schizo_bus_mmap: prot %d flags %d pa %llx\n",
717 	    prot, flags, (unsigned long long)paddr));
718 
719 	if (t->parent == 0 || t->parent->sparc_bus_mmap == 0) {
720 		printf("\nschizo_bus_mmap: invalid parent");
721 		return (-1);
722 	}
723 
724 	for (i = 0; i < pbm->sp_nrange; i++) {
725 		bus_addr_t paddr;
726 
727 		if (((pbm->sp_range[i].cspace >> 24) & 0x03) != ss)
728 			continue;
729 
730 		paddr = pbm->sp_range[i].phys_lo + offset;
731 		paddr |= ((bus_addr_t)pbm->sp_range[i].phys_hi) << 32;
732 		return ((*t->parent->sparc_bus_mmap)
733 		    (t, t0, paddr, off, prot, flags));
734 	}
735 
736 	return (-1);
737 }
738 
739 bus_addr_t
schizo_bus_addr(bus_space_tag_t t,bus_space_tag_t t0,bus_space_handle_t h)740 schizo_bus_addr(bus_space_tag_t t, bus_space_tag_t t0, bus_space_handle_t h)
741 {
742 	struct schizo_pbm *pbm = t->cookie;
743 	bus_addr_t addr;
744 	int i, ss;
745 
746 	ss = t->default_type;
747 
748 	if (t->parent == 0 || t->parent->sparc_bus_addr == 0) {
749 		printf("\nschizo_bus_addr: invalid parent");
750 		return (-1);
751 	}
752 
753 	t = t->parent;
754 
755 	addr = ((*t->sparc_bus_addr)(t, t0, h));
756 	if (addr == -1)
757 		return (-1);
758 
759 	for (i = 0; i < pbm->sp_nrange; i++) {
760 		if (((pbm->sp_range[i].cspace >> 24) & 0x03) != ss)
761 			continue;
762 
763 		return (BUS_ADDR_PADDR(addr) - pbm->sp_range[i].phys_lo);
764 	}
765 
766 	return (-1);
767 }
768 
769 void *
schizo_intr_establish(bus_space_tag_t t,bus_space_tag_t t0,int ihandle,int level,int flags,int (* handler)(void *),void * arg,const char * what)770 schizo_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
771     int level, int flags, int (*handler)(void *), void *arg, const char *what)
772 {
773 	struct schizo_pbm *pbm = t->cookie;
774 	struct intrhand *ih = NULL;
775 	volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL;
776 	int ino;
777 	long vec = INTVEC(ihandle);
778 
779 	vec = INTVEC(ihandle);
780 	ino = INTINO(vec);
781 
782 	if (level == IPL_NONE)
783 		level = INTLEV(vec);
784 	if (level == IPL_NONE) {
785 		printf(": no IPL, setting IPL 2.\n");
786 		level = 2;
787 	}
788 
789 	if ((flags & BUS_INTR_ESTABLISH_SOFTINTR) == 0) {
790 		struct schizo_pbm_regs *pbmreg;
791 
792 		pbmreg = bus_space_vaddr(pbm->sp_regt, pbm->sp_regh);
793 		intrmapptr = &pbmreg->imap[ino];
794 		intrclrptr = &pbmreg->iclr[ino];
795 		if (INTIGN(vec) == 0)
796 			ino |= (*intrmapptr) & INTMAP_IGN;
797 		else
798 			ino |= vec & INTMAP_IGN;
799 	}
800 
801 	ih = bus_intr_allocate(t0, handler, arg, ino, level, intrmapptr,
802 	    intrclrptr, what);
803 	if (ih == NULL)
804 		return (NULL);
805 
806 	if (flags & BUS_INTR_ESTABLISH_MPSAFE)
807 		ih->ih_mpsafe = 1;
808 
809 	intr_establish(ih);
810 
811 	if (intrmapptr != NULL) {
812 		u_int64_t intrmap;
813 
814 		intrmap = *intrmapptr;
815 		intrmap |= INTMAP_V;
816 		*intrmapptr = intrmap;
817 		intrmap = *intrmapptr;
818 		ih->ih_number |= intrmap & INTMAP_INR;
819 	}
820 
821 	return (ih);
822 }
823 
824 #ifdef DDB
825 void
schizo_xir(void * arg,int cpu)826 schizo_xir(void *arg, int cpu)
827 {
828 	struct schizo_softc *sc = arg;
829 
830 	schizo_write(sc, TOM_RESET_GEN, TOM_RESET_GEN_XIR);
831 }
832 #endif
833 
834 const struct cfattach schizo_ca = {
835 	sizeof(struct schizo_softc), schizo_match, schizo_attach
836 };
837 
838 struct cfdriver schizo_cd = {
839 	NULL, "schizo", DV_DULL
840 };
841