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