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