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