Annotation of sys/arch/hppa64/dev/elroy.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: elroy.c,v 1.4 2006/12/14 17:36:12 kettenis Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Michael Shalayeff
! 5: * All rights reserved.
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
! 16: * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 17: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: #include "cardbus.h"
! 21:
! 22: #include <sys/param.h>
! 23: #include <sys/systm.h>
! 24: #include <sys/device.h>
! 25: #include <sys/reboot.h>
! 26: #include <sys/malloc.h>
! 27: #include <sys/extent.h>
! 28:
! 29: #include <machine/iomod.h>
! 30: #include <machine/autoconf.h>
! 31:
! 32: #include <arch/hppa/dev/cpudevs.h>
! 33:
! 34: #if NCARDBUS > 0
! 35: #include <dev/cardbus/rbus.h>
! 36: #endif
! 37:
! 38: #include <dev/pci/pcireg.h>
! 39: #include <dev/pci/pcivar.h>
! 40: #include <dev/pci/pcidevs.h>
! 41:
! 42: #include <hppa64/dev/elroyreg.h>
! 43: #include <hppa64/dev/elroyvar.h>
! 44:
! 45: #define ELROY_MEM_CHUNK 0x800000
! 46: #define ELROY_MEM_WINDOW (2 * ELROY_MEM_CHUNK)
! 47:
! 48: /* global interrupt masks */
! 49: u_int64_t cpu_maskfree;
! 50: volatile u_int64_t imask[NIPL];
! 51:
! 52: int elroymatch(struct device *, void *, void *);
! 53: void elroyattach(struct device *, struct device *, void *);
! 54: int elroy_intr(void *);
! 55:
! 56: struct cfattach elroy_ca = {
! 57: sizeof(struct elroy_softc), elroymatch, elroyattach
! 58: };
! 59:
! 60: struct cfdriver elroy_cd = {
! 61: NULL, "elroy", DV_DULL
! 62: };
! 63:
! 64: int
! 65: elroymatch(parent, cfdata, aux)
! 66: struct device *parent;
! 67: void *cfdata;
! 68: void *aux;
! 69: {
! 70: struct confargs *ca = aux;
! 71: /* struct cfdata *cf = cfdata; */
! 72:
! 73: if ((ca->ca_name && !strcmp(ca->ca_name, "lba")) ||
! 74: (ca->ca_type.iodc_type == HPPA_TYPE_BRIDGE &&
! 75: ca->ca_type.iodc_sv_model == HPPA_BRIDGE_DINO &&
! 76: ca->ca_type.iodc_model == 0x78))
! 77: return (1);
! 78:
! 79: return (0);
! 80: }
! 81:
! 82: void
! 83: elroy_write32(volatile u_int32_t *p, u_int32_t v)
! 84: {
! 85: *p = v;
! 86: }
! 87:
! 88: u_int32_t
! 89: elroy_read32(volatile u_int32_t *p)
! 90: {
! 91: return *p;
! 92: }
! 93:
! 94: void
! 95: elroy_attach_hook(struct device *parent, struct device *self,
! 96: struct pcibus_attach_args *pba)
! 97: {
! 98:
! 99: }
! 100:
! 101: int
! 102: elroy_maxdevs(void *v, int bus)
! 103: {
! 104: return (32);
! 105: }
! 106:
! 107: pcitag_t
! 108: elroy_make_tag(void *v, int bus, int dev, int func)
! 109: {
! 110: if (bus > 255 || dev > 31 || func > 7)
! 111: panic("elroy_make_tag: bad request");
! 112:
! 113: return ((bus << 16) | (dev << 11) | (func << 8));
! 114: }
! 115:
! 116: void
! 117: elroy_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func)
! 118: {
! 119: *bus = (tag >> 16) & 0xff;
! 120: *dev = (tag >> 11) & 0x1f;
! 121: *func= (tag >> 8) & 0x07;
! 122: }
! 123:
! 124: pcireg_t
! 125: elroy_conf_read(void *v, pcitag_t tag, int reg)
! 126: {
! 127: struct elroy_softc *sc = v;
! 128: volatile struct elroy_regs *r = sc->sc_regs;
! 129: u_int32_t arb_mask, err_cfg, control;
! 130: pcireg_t data, data1;
! 131:
! 132: /* printf("elroy_conf_read(%p, 0x%08x, 0x%x)", v, tag, reg); */
! 133: arb_mask = elroy_read32(&r->arb_mask);
! 134: err_cfg = elroy_read32(&r->err_cfg);
! 135: control = elroy_read32(&r->control);
! 136: if (!arb_mask)
! 137: elroy_write32(&r->arb_mask, htole64(ELROY_ARB_ENABLE));
! 138: elroy_write32(&r->err_cfg, err_cfg |
! 139: htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM));
! 140: elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) &
! 141: ~htole32(ELROY_CONTROL_HF));
! 142:
! 143: elroy_write32(&r->pci_conf_addr, htole32(tag | reg));
! 144: data1 = elroy_read32(&r->pci_conf_addr);
! 145: data = elroy_read32(&r->pci_conf_data);
! 146:
! 147: elroy_write32(&r->control, control |
! 148: htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL));
! 149: elroy_write32(&r->control, control);
! 150: elroy_write32(&r->err_cfg, err_cfg);
! 151: if (!arb_mask)
! 152: elroy_write32(&r->arb_mask, arb_mask);
! 153:
! 154: data = letoh32(data);
! 155: /* printf("=0x%08x (@ 0x%08x)\n", data, letoh32(data1)); */
! 156: return (data);
! 157: }
! 158:
! 159: void
! 160: elroy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
! 161: {
! 162: struct elroy_softc *sc = v;
! 163: volatile struct elroy_regs *r = sc->sc_regs;
! 164: u_int32_t arb_mask, err_cfg, control;
! 165: pcireg_t data1;
! 166:
! 167: /* printf("elroy_conf_write(%p, 0x%08x, 0x%x, 0x%x)\n", v, tag, reg, data); */
! 168: arb_mask = elroy_read32(&r->arb_mask);
! 169: err_cfg = elroy_read32(&r->err_cfg);
! 170: control = elroy_read32(&r->control);
! 171: if (!arb_mask)
! 172: elroy_write32(&r->arb_mask, htole64(ELROY_ARB_ENABLE));
! 173: elroy_write32(&r->err_cfg, err_cfg |
! 174: htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM));
! 175: elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) &
! 176: ~htole32(ELROY_CONTROL_HF));
! 177:
! 178: /* fix coalescing config writes errata by interleaving w/ a read */
! 179: elroy_write32(&r->pci_conf_addr, htole32(tag | PCI_ID_REG));
! 180: data1 = elroy_read32(&r->pci_conf_addr);
! 181: data1 = elroy_read32(&r->pci_conf_data);
! 182:
! 183: elroy_write32(&r->pci_conf_addr, htole32(tag | reg));
! 184: data1 = elroy_read32(&r->pci_conf_addr);
! 185: elroy_write32(&r->pci_conf_data, htole32(data));
! 186: data1 = elroy_read32(&r->pci_conf_addr);
! 187:
! 188: elroy_write32(&r->control, control |
! 189: htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL));
! 190: elroy_write32(&r->control, control);
! 191: elroy_write32(&r->err_cfg, err_cfg);
! 192: if (!arb_mask)
! 193: elroy_write32(&r->arb_mask, arb_mask);
! 194: }
! 195:
! 196: int
! 197: elroy_iomap(void *v, bus_addr_t bpa, bus_size_t size,
! 198: int flags, bus_space_handle_t *bshp)
! 199: {
! 200: struct elroy_softc *sc = v;
! 201: /* volatile struct elroy_regs *r = sc->sc_regs; */
! 202: int error;
! 203:
! 204: if ((error = bus_space_map(sc->sc_bt, bpa + sc->sc_iobase, size,
! 205: flags, bshp)))
! 206: return (error);
! 207:
! 208: return (0);
! 209: }
! 210:
! 211: int
! 212: elroy_memmap(void *v, bus_addr_t bpa, bus_size_t size,
! 213: int flags, bus_space_handle_t *bshp)
! 214: {
! 215: struct elroy_softc *sc = v;
! 216: /* volatile struct elroy_regs *r = sc->sc_regs; */
! 217: int error;
! 218:
! 219: bpa |= 0xffffffff00000000ULL;
! 220: if ((error = bus_space_map(sc->sc_bt, bpa, size, flags, bshp)))
! 221: return (error);
! 222:
! 223: return (0);
! 224: }
! 225:
! 226: int
! 227: elroy_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset,
! 228: bus_size_t size, bus_space_handle_t *nbshp)
! 229: {
! 230: *nbshp = bsh + offset;
! 231: return (0);
! 232: }
! 233:
! 234: int
! 235: elroy_ioalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
! 236: bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
! 237: bus_space_handle_t *bshp)
! 238: {
! 239: struct elroy_softc *sc = v;
! 240: volatile struct elroy_regs *r = sc->sc_regs;
! 241: bus_addr_t iostart, ioend;
! 242:
! 243: iostart = r->io_base & ~htole32(ELROY_BASE_RE);
! 244: ioend = iostart + ~htole32(r->io_mask) + 1;
! 245: if (rstart < iostart || rend > ioend)
! 246: panic("elroy_ioalloc: bad region start/end");
! 247:
! 248: rstart += sc->sc_iobase;
! 249: rend += sc->sc_iobase;
! 250: if (bus_space_alloc(sc->sc_bt, rstart, rend, size,
! 251: align, boundary, flags, addrp, bshp))
! 252: return (ENOMEM);
! 253:
! 254: return (0);
! 255: }
! 256:
! 257: int
! 258: elroy_memalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
! 259: bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
! 260: bus_space_handle_t *bshp)
! 261: {
! 262: struct elroy_softc *sc = v;
! 263: /* volatile struct elroy_regs *r = sc->sc_regs; */
! 264:
! 265: if (bus_space_alloc(sc->sc_bt, rstart, rend, size,
! 266: align, boundary, flags, addrp, bshp))
! 267: return (ENOMEM);
! 268:
! 269: return (0);
! 270: }
! 271:
! 272: void
! 273: elroy_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
! 274: {
! 275: struct elroy_softc *sc = v;
! 276:
! 277: bus_space_free(sc->sc_bt, bsh, size);
! 278: }
! 279:
! 280: void
! 281: elroy_free(void *v, bus_space_handle_t bh, bus_size_t size)
! 282: {
! 283: /* should be enough */
! 284: elroy_unmap(v, bh, size);
! 285: }
! 286:
! 287: void
! 288: elroy_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
! 289: {
! 290: struct elroy_softc *sc = v;
! 291: volatile struct elroy_regs *r = sc->sc_regs;
! 292: u_int32_t data;
! 293:
! 294: sync_caches();
! 295: if (op & BUS_SPACE_BARRIER_WRITE) {
! 296: data = r->pci_id; /* flush write fifo */
! 297: sync_caches();
! 298: }
! 299: }
! 300:
! 301: #if NCARDBUS > 0
! 302: void *
! 303: elroy_alloc_parent(struct device *self, struct pci_attach_args *pa, int io)
! 304: {
! 305: #if 0 /* TODO */
! 306:
! 307: struct elroy_softc *sc = pa->pa_pc->_cookie;
! 308: struct extent *ex;
! 309: bus_space_tag_t tag;
! 310: bus_addr_t start;
! 311: bus_size_t size;
! 312:
! 313: if (io) {
! 314: ex = sc->sc_ioex;
! 315: tag = pa->pa_iot;
! 316: start = 0xa000;
! 317: size = 0x1000;
! 318: } else {
! 319: if (!sc->sc_memex) {
! 320: bus_space_handle_t memh;
! 321: bus_addr_t mem_start;
! 322:
! 323: if (elroy_memalloc(sc, 0xf0800000, 0xff7fffff,
! 324: ELROY_MEM_WINDOW, ELROY_MEM_WINDOW, EX_NOBOUNDARY,
! 325: 0, &mem_start, &memh))
! 326: return (NULL);
! 327:
! 328: snprintf(sc->sc_memexname, sizeof(sc->sc_memexname),
! 329: "%s_mem", sc->sc_dv.dv_xname);
! 330: if ((sc->sc_memex = extent_create(sc->sc_memexname,
! 331: mem_start, mem_start + ELROY_MEM_WINDOW, M_DEVBUF,
! 332: NULL, 0, EX_NOWAIT | EX_MALLOCOK)) == NULL) {
! 333: extent_destroy(sc->sc_ioex);
! 334: bus_space_free(sc->sc_bt, memh,
! 335: ELROY_MEM_WINDOW);
! 336: return (NULL);
! 337: }
! 338: }
! 339: ex = sc->sc_memex;
! 340: tag = pa->pa_memt;
! 341: start = ex->ex_start;
! 342: size = ELROY_MEM_CHUNK;
! 343: }
! 344:
! 345: if (extent_alloc_subregion(ex, start, ex->ex_end, size, size, 0,
! 346: EX_NOBOUNDARY, EX_NOWAIT, &start))
! 347: return (NULL);
! 348:
! 349: extent_free(ex, start, size, EX_NOWAIT);
! 350: return rbus_new_root_share(tag, ex, start, size, 0);
! 351: #else
! 352: return (NULL);
! 353: #endif
! 354: }
! 355: #endif
! 356:
! 357: u_int8_t
! 358: elroy_r1(void *v, bus_space_handle_t h, bus_size_t o)
! 359: {
! 360: h += o;
! 361: return *(volatile u_int8_t *)h;
! 362: }
! 363:
! 364: u_int16_t
! 365: elroy_r2(void *v, bus_space_handle_t h, bus_size_t o)
! 366: {
! 367: volatile u_int16_t *p;
! 368:
! 369: h += o;
! 370: p = (volatile u_int16_t *)h;
! 371: return (letoh16(*p));
! 372: }
! 373:
! 374: u_int32_t
! 375: elroy_r4(void *v, bus_space_handle_t h, bus_size_t o)
! 376: {
! 377: u_int32_t data;
! 378:
! 379: h += o;
! 380: data = *(volatile u_int32_t *)h;
! 381: return (letoh32(data));
! 382: }
! 383:
! 384: u_int64_t
! 385: elroy_r8(void *v, bus_space_handle_t h, bus_size_t o)
! 386: {
! 387: u_int64_t data;
! 388:
! 389: h += o;
! 390: data = *(volatile u_int64_t *)h;
! 391: return (letoh64(data));
! 392: }
! 393:
! 394: void
! 395: elroy_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv)
! 396: {
! 397: h += o;
! 398: *(volatile u_int8_t *)h = vv;
! 399: }
! 400:
! 401: void
! 402: elroy_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv)
! 403: {
! 404: volatile u_int16_t *p;
! 405:
! 406: h += o;
! 407: p = (volatile u_int16_t *)h;
! 408: *p = htole16(vv);
! 409: }
! 410:
! 411: void
! 412: elroy_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv)
! 413: {
! 414: h += o;
! 415: vv = htole32(vv);
! 416: *(volatile u_int32_t *)h = vv;
! 417: }
! 418:
! 419: void
! 420: elroy_w8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv)
! 421: {
! 422: h += o;
! 423: *(volatile u_int64_t *)h = htole64(vv);
! 424: }
! 425:
! 426:
! 427: void
! 428: elroy_rm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
! 429: {
! 430: volatile u_int8_t *p;
! 431:
! 432: h += o;
! 433: p = (volatile u_int8_t *)h;
! 434: while (c--)
! 435: *a++ = *p;
! 436: }
! 437:
! 438: void
! 439: elroy_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
! 440: {
! 441: volatile u_int16_t *p;
! 442:
! 443: h += o;
! 444: p = (volatile u_int16_t *)h;
! 445: while (c--)
! 446: *a++ = letoh16(*p);
! 447: }
! 448:
! 449: void
! 450: elroy_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
! 451: {
! 452: volatile u_int32_t *p;
! 453:
! 454: h += o;
! 455: p = (volatile u_int32_t *)h;
! 456: while (c--)
! 457: *a++ = letoh32(*p);
! 458: }
! 459:
! 460: void
! 461: elroy_rm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
! 462: {
! 463: volatile u_int64_t *p;
! 464:
! 465: h += o;
! 466: p = (volatile u_int64_t *)h;
! 467: while (c--)
! 468: *a++ = letoh64(*p);
! 469: }
! 470:
! 471: void
! 472: elroy_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
! 473: {
! 474: volatile u_int8_t *p;
! 475:
! 476: h += o;
! 477: p = (volatile u_int8_t *)h;
! 478: while (c--)
! 479: *p = *a++;
! 480: }
! 481:
! 482: void
! 483: elroy_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
! 484: {
! 485: volatile u_int16_t *p;
! 486:
! 487: h += o;
! 488: p = (volatile u_int16_t *)h;
! 489: while (c--)
! 490: *p = htole16(*a++);
! 491: }
! 492:
! 493: void
! 494: elroy_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
! 495: {
! 496: volatile u_int32_t *p;
! 497:
! 498: h += o;
! 499: p = (volatile u_int32_t *)h;
! 500: while (c--)
! 501: *p = htole32(*a++);
! 502: }
! 503:
! 504: void
! 505: elroy_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
! 506: {
! 507: volatile u_int64_t *p;
! 508:
! 509: h += o;
! 510: p = (volatile u_int64_t *)h;
! 511: while (c--)
! 512: *p = htole64(*a++);
! 513: }
! 514:
! 515: void
! 516: elroy_sm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
! 517: {
! 518: volatile u_int8_t *p;
! 519:
! 520: h += o;
! 521: p = (volatile u_int8_t *)h;
! 522: while (c--)
! 523: *p = vv;
! 524: }
! 525:
! 526: void
! 527: elroy_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
! 528: {
! 529: volatile u_int16_t *p;
! 530:
! 531: h += o;
! 532: p = (volatile u_int16_t *)h;
! 533: vv = htole16(vv);
! 534: while (c--)
! 535: *p = vv;
! 536: }
! 537:
! 538: void
! 539: elroy_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
! 540: {
! 541: volatile u_int32_t *p;
! 542:
! 543: h += o;
! 544: p = (volatile u_int32_t *)h;
! 545: vv = htole32(vv);
! 546: while (c--)
! 547: *p = vv;
! 548: }
! 549:
! 550: void
! 551: elroy_sm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
! 552: {
! 553: volatile u_int64_t *p;
! 554:
! 555: h += o;
! 556: p = (volatile u_int64_t *)h;
! 557: vv = htole64(vv);
! 558: while (c--)
! 559: *p = vv;
! 560: }
! 561:
! 562: void
! 563: elroy_rrm_2(void *v, bus_space_handle_t h, bus_size_t o,
! 564: u_int8_t *a, bus_size_t c)
! 565: {
! 566: volatile u_int16_t *p, *q = (u_int16_t *)a;
! 567:
! 568: h += o;
! 569: p = (volatile u_int16_t *)h;
! 570: c /= 2;
! 571: while (c--)
! 572: *q++ = *p;
! 573: }
! 574:
! 575: void
! 576: elroy_rrm_4(void *v, bus_space_handle_t h, bus_size_t o,
! 577: u_int8_t *a, bus_size_t c)
! 578: {
! 579: volatile u_int32_t *p, *q = (u_int32_t *)a;
! 580:
! 581: h += o;
! 582: p = (volatile u_int32_t *)h;
! 583: c /= 4;
! 584: while (c--)
! 585: *q++ = *p;
! 586: }
! 587:
! 588: void
! 589: elroy_rrm_8(void *v, bus_space_handle_t h, bus_size_t o,
! 590: u_int8_t *a, bus_size_t c)
! 591: {
! 592: volatile u_int64_t *p, *q = (u_int64_t *)a;
! 593:
! 594: h += o;
! 595: p = (volatile u_int64_t *)h;
! 596: c /= 8;
! 597: while (c--)
! 598: *q++ = *p;
! 599: }
! 600:
! 601: void
! 602: elroy_wrm_2(void *v, bus_space_handle_t h, bus_size_t o,
! 603: const u_int8_t *a, bus_size_t c)
! 604: {
! 605: volatile u_int16_t *p;
! 606: const u_int16_t *q = (const u_int16_t *)a;
! 607:
! 608: h += o;
! 609: p = (volatile u_int16_t *)h;
! 610: c /= 2;
! 611: while (c--)
! 612: *p = *q++;
! 613: }
! 614:
! 615: void
! 616: elroy_wrm_4(void *v, bus_space_handle_t h, bus_size_t o,
! 617: const u_int8_t *a, bus_size_t c)
! 618: {
! 619: volatile u_int32_t *p;
! 620: const u_int32_t *q = (const u_int32_t *)a;
! 621:
! 622: h += o;
! 623: p = (volatile u_int32_t *)h;
! 624: c /= 4;
! 625: while (c--)
! 626: *p = *q++;
! 627: }
! 628:
! 629: void
! 630: elroy_wrm_8(void *v, bus_space_handle_t h, bus_size_t o,
! 631: const u_int8_t *a, bus_size_t c)
! 632: {
! 633: volatile u_int64_t *p;
! 634: const u_int64_t *q = (const u_int64_t *)a;
! 635:
! 636: h += o;
! 637: p = (volatile u_int64_t *)h;
! 638: c /= 8;
! 639: while (c--)
! 640: *p = *q++;
! 641: }
! 642:
! 643: void
! 644: elroy_rr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
! 645: {
! 646: volatile u_int8_t *p;
! 647:
! 648: h += o;
! 649: p = (volatile u_int8_t *)h;
! 650: while (c--)
! 651: *a++ = *p++;
! 652: }
! 653:
! 654: void
! 655: elroy_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
! 656: {
! 657: volatile u_int16_t *p, data;
! 658:
! 659: h += o;
! 660: p = (volatile u_int16_t *)h;
! 661: while (c--) {
! 662: data = *p++;
! 663: *a++ = letoh16(data);
! 664: }
! 665: }
! 666:
! 667: void
! 668: elroy_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
! 669: {
! 670: volatile u_int32_t *p, data;
! 671:
! 672: h += o;
! 673: p = (volatile u_int32_t *)h;
! 674: while (c--) {
! 675: data = *p++;
! 676: *a++ = letoh32(data);
! 677: }
! 678: }
! 679:
! 680: void
! 681: elroy_rr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
! 682: {
! 683: volatile u_int64_t *p, data;
! 684:
! 685: h += o;
! 686: p = (volatile u_int64_t *)h;
! 687: while (c--) {
! 688: data = *p++;
! 689: *a++ = letoh64(data);
! 690: }
! 691: }
! 692:
! 693: void
! 694: elroy_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
! 695: {
! 696: volatile u_int8_t *p;
! 697:
! 698: h += o;
! 699: p = (volatile u_int8_t *)h;
! 700: while (c--)
! 701: *p++ = *a++;
! 702: }
! 703:
! 704: void
! 705: elroy_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
! 706: {
! 707: volatile u_int16_t *p, data;
! 708:
! 709: h += o;
! 710: p = (volatile u_int16_t *)h;
! 711: while (c--) {
! 712: data = *a++;
! 713: *p++ = htole16(data);
! 714: }
! 715: }
! 716:
! 717: void
! 718: elroy_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
! 719: {
! 720: volatile u_int32_t *p, data;
! 721:
! 722: h += o;
! 723: p = (volatile u_int32_t *)h;
! 724: while (c--) {
! 725: data = *a++;
! 726: *p++ = htole32(data);
! 727: }
! 728: }
! 729:
! 730: void
! 731: elroy_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
! 732: {
! 733: volatile u_int64_t *p, data;
! 734:
! 735: h += o;
! 736: p = (volatile u_int64_t *)h;
! 737: while (c--) {
! 738: data = *a++;
! 739: *p++ = htole64(data);
! 740: }
! 741: }
! 742:
! 743: void
! 744: elroy_rrr_2(void *v, bus_space_handle_t h, bus_size_t o,
! 745: u_int8_t *a, bus_size_t c)
! 746: {
! 747: volatile u_int16_t *p, *q = (u_int16_t *)a;
! 748:
! 749: c /= 2;
! 750: h += o;
! 751: p = (volatile u_int16_t *)h;
! 752: while (c--)
! 753: *q++ = *p++;
! 754: }
! 755:
! 756: void
! 757: elroy_rrr_4(void *v, bus_space_handle_t h, bus_size_t o,
! 758: u_int8_t *a, bus_size_t c)
! 759: {
! 760: volatile u_int32_t *p, *q = (u_int32_t *)a;
! 761:
! 762: c /= 4;
! 763: h += o;
! 764: p = (volatile u_int32_t *)h;
! 765: while (c--)
! 766: *q++ = *p++;
! 767: }
! 768:
! 769: void
! 770: elroy_rrr_8(void *v, bus_space_handle_t h, bus_size_t o,
! 771: u_int8_t *a, bus_size_t c)
! 772: {
! 773: volatile u_int64_t *p, *q = (u_int64_t *)a;
! 774:
! 775: c /= 8;
! 776: h += o;
! 777: p = (volatile u_int64_t *)h;
! 778: while (c--)
! 779: *q++ = *p++;
! 780: }
! 781:
! 782: void
! 783: elroy_wrr_2(void *v, bus_space_handle_t h, bus_size_t o,
! 784: const u_int8_t *a, bus_size_t c)
! 785: {
! 786: volatile u_int16_t *p;
! 787: const u_int16_t *q = (u_int16_t *)a;
! 788:
! 789: c /= 2;
! 790: h += o;
! 791: p = (volatile u_int16_t *)h;
! 792: while (c--)
! 793: *p++ = *q++;
! 794: }
! 795:
! 796: void
! 797: elroy_wrr_4(void *v, bus_space_handle_t h, bus_size_t o,
! 798: const u_int8_t *a, bus_size_t c)
! 799: {
! 800: volatile u_int32_t *p;
! 801: const u_int32_t *q = (u_int32_t *)a;
! 802:
! 803: c /= 4;
! 804: h += o;
! 805: p = (volatile u_int32_t *)h;
! 806: while (c--)
! 807: *p++ = *q++;
! 808: }
! 809:
! 810: void
! 811: elroy_wrr_8(void *v, bus_space_handle_t h, bus_size_t o,
! 812: const u_int8_t *a, bus_size_t c)
! 813: {
! 814: volatile u_int64_t *p;
! 815: const u_int64_t *q = (u_int64_t *)a;
! 816:
! 817: c /= 8;
! 818: h += o;
! 819: p = (volatile u_int64_t *)h;
! 820: while (c--)
! 821: *p++ = *q++;
! 822: }
! 823:
! 824: void
! 825: elroy_sr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
! 826: {
! 827: volatile u_int8_t *p;
! 828:
! 829: h += o;
! 830: p = (volatile u_int8_t *)h;
! 831: while (c--)
! 832: *p++ = vv;
! 833: }
! 834:
! 835: void
! 836: elroy_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
! 837: {
! 838: volatile u_int16_t *p;
! 839:
! 840: h += o;
! 841: vv = htole16(vv);
! 842: p = (volatile u_int16_t *)h;
! 843: while (c--)
! 844: *p++ = vv;
! 845: }
! 846:
! 847: void
! 848: elroy_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
! 849: {
! 850: volatile u_int32_t *p;
! 851:
! 852: h += o;
! 853: vv = htole32(vv);
! 854: p = (volatile u_int32_t *)h;
! 855: while (c--)
! 856: *p++ = vv;
! 857: }
! 858:
! 859: void
! 860: elroy_sr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
! 861: {
! 862: volatile u_int64_t *p;
! 863:
! 864: h += o;
! 865: vv = htole64(vv);
! 866: p = (volatile u_int64_t *)h;
! 867: while (c--)
! 868: *p++ = vv;
! 869: }
! 870:
! 871: void
! 872: elroy_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1,
! 873: bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
! 874: {
! 875: while (c--)
! 876: elroy_w1(v, h1, o1++, elroy_r1(v, h2, o2++));
! 877: }
! 878:
! 879: void
! 880: elroy_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1,
! 881: bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
! 882: {
! 883: while (c--) {
! 884: elroy_w2(v, h1, o1, elroy_r2(v, h2, o2));
! 885: o1 += 2;
! 886: o2 += 2;
! 887: }
! 888: }
! 889:
! 890: void
! 891: elroy_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1,
! 892: bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
! 893: {
! 894: while (c--) {
! 895: elroy_w4(v, h1, o1, elroy_r4(v, h2, o2));
! 896: o1 += 4;
! 897: o2 += 4;
! 898: }
! 899: }
! 900:
! 901: void
! 902: elroy_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1,
! 903: bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
! 904: {
! 905: while (c--) {
! 906: elroy_w8(v, h1, o1, elroy_r8(v, h2, o2));
! 907: o1 += 8;
! 908: o2 += 8;
! 909: }
! 910: }
! 911:
! 912: const struct hppa64_bus_space_tag elroy_iomemt = {
! 913: NULL,
! 914:
! 915: NULL, elroy_unmap, elroy_subregion, NULL, elroy_free,
! 916: elroy_barrier,
! 917: elroy_r1, elroy_r2, elroy_r4, elroy_r8,
! 918: elroy_w1, elroy_w2, elroy_w4, elroy_w8,
! 919: elroy_rm_1, elroy_rm_2, elroy_rm_4, elroy_rm_8,
! 920: elroy_wm_1, elroy_wm_2, elroy_wm_4, elroy_wm_8,
! 921: elroy_sm_1, elroy_sm_2, elroy_sm_4, elroy_sm_8,
! 922: elroy_rrm_2, elroy_rrm_4, elroy_rrm_8,
! 923: elroy_wrm_2, elroy_wrm_4, elroy_wrm_8,
! 924: elroy_rr_1, elroy_rr_2, elroy_rr_4, elroy_rr_8,
! 925: elroy_wr_1, elroy_wr_2, elroy_wr_4, elroy_wr_8,
! 926: elroy_rrr_2, elroy_rrr_4, elroy_rrr_8,
! 927: elroy_wrr_2, elroy_wrr_4, elroy_wrr_8,
! 928: elroy_sr_1, elroy_sr_2, elroy_sr_4, elroy_sr_8,
! 929: elroy_cp_1, elroy_cp_2, elroy_cp_4, elroy_cp_8
! 930: };
! 931:
! 932: int
! 933: elroy_dmamap_create(void *v, bus_size_t size, int nsegments,
! 934: bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
! 935: {
! 936: struct elroy_softc *sc = v;
! 937:
! 938: /* TODO check the addresses, boundary, enable dma */
! 939:
! 940: return (bus_dmamap_create(sc->sc_dmat, size, nsegments,
! 941: maxsegsz, boundary, flags, dmamp));
! 942: }
! 943:
! 944: void
! 945: elroy_dmamap_destroy(void *v, bus_dmamap_t map)
! 946: {
! 947: struct elroy_softc *sc = v;
! 948:
! 949: bus_dmamap_destroy(sc->sc_dmat, map);
! 950: }
! 951:
! 952: int
! 953: elroy_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
! 954: struct proc *p, int flags)
! 955: {
! 956: struct elroy_softc *sc = v;
! 957:
! 958: return (bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags));
! 959: }
! 960:
! 961: int
! 962: elroy_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags)
! 963: {
! 964: struct elroy_softc *sc = v;
! 965:
! 966: return (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags));
! 967: }
! 968:
! 969: int
! 970: elroy_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
! 971: {
! 972: struct elroy_softc *sc = v;
! 973:
! 974: return (bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags));
! 975: }
! 976:
! 977: int
! 978: elroy_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
! 979: int nsegs, bus_size_t size, int flags)
! 980: {
! 981: struct elroy_softc *sc = v;
! 982:
! 983: return (bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags));
! 984: }
! 985:
! 986: void
! 987: elroy_dmamap_unload(void *v, bus_dmamap_t map)
! 988: {
! 989: struct elroy_softc *sc = v;
! 990:
! 991: bus_dmamap_unload(sc->sc_dmat, map);
! 992: }
! 993:
! 994: void
! 995: elroy_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off,
! 996: bus_size_t len, int ops)
! 997: {
! 998: struct elroy_softc *sc = v;
! 999:
! 1000: return (bus_dmamap_sync(sc->sc_dmat, map, off, len, ops));
! 1001: }
! 1002:
! 1003: int
! 1004: elroy_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
! 1005: bus_size_t boundary, bus_dma_segment_t *segs,
! 1006: int nsegs, int *rsegs, int flags)
! 1007: {
! 1008: struct elroy_softc *sc = v;
! 1009:
! 1010: return (bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary,
! 1011: segs, nsegs, rsegs, flags));
! 1012: }
! 1013:
! 1014: void
! 1015: elroy_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
! 1016: {
! 1017: struct elroy_softc *sc = v;
! 1018:
! 1019: bus_dmamem_free(sc->sc_dmat, segs, nsegs);
! 1020: }
! 1021:
! 1022: int
! 1023: elroy_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
! 1024: caddr_t *kvap, int flags)
! 1025: {
! 1026: struct elroy_softc *sc = v;
! 1027:
! 1028: return (bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags));
! 1029: }
! 1030:
! 1031: void
! 1032: elroy_dmamem_unmap(void *v, caddr_t kva, size_t size)
! 1033: {
! 1034: struct elroy_softc *sc = v;
! 1035:
! 1036: bus_dmamem_unmap(sc->sc_dmat, kva, size);
! 1037: }
! 1038:
! 1039: paddr_t
! 1040: elroy_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
! 1041: int prot, int flags)
! 1042: {
! 1043: struct elroy_softc *sc = v;
! 1044:
! 1045: return (bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags));
! 1046: }
! 1047:
! 1048: const struct hppa64_bus_dma_tag elroy_dmat = {
! 1049: NULL,
! 1050: elroy_dmamap_create, elroy_dmamap_destroy,
! 1051: elroy_dmamap_load, elroy_dmamap_load_mbuf,
! 1052: elroy_dmamap_load_uio, elroy_dmamap_load_raw,
! 1053: elroy_dmamap_unload, elroy_dmamap_sync,
! 1054:
! 1055: elroy_dmamem_alloc, elroy_dmamem_free, elroy_dmamem_map,
! 1056: elroy_dmamem_unmap, elroy_dmamem_mmap
! 1057: };
! 1058:
! 1059: const struct hppa64_pci_chipset_tag elroy_pc = {
! 1060: NULL,
! 1061: elroy_attach_hook, elroy_maxdevs, elroy_make_tag, elroy_decompose_tag,
! 1062: elroy_conf_read, elroy_conf_write,
! 1063: apic_intr_map, apic_intr_string,
! 1064: apic_intr_establish, apic_intr_disestablish,
! 1065: #if NCARDBUS > 0
! 1066: elroy_alloc_parent
! 1067: #else
! 1068: NULL
! 1069: #endif
! 1070: };
! 1071:
! 1072: int
! 1073: elroyprint(void *aux, const char *pnp)
! 1074: {
! 1075: struct pcibus_attach_args *pba = aux;
! 1076:
! 1077: if (pnp)
! 1078: printf("%s at %s\n", pba->pba_busname, pnp);
! 1079: return (UNCONF);
! 1080: }
! 1081:
! 1082: void
! 1083: elroyattach(parent, self, aux)
! 1084: struct device *parent;
! 1085: struct device *self;
! 1086: void *aux;
! 1087: {
! 1088: struct elroy_softc *sc = (struct elroy_softc *)self;
! 1089: struct confargs *ca = (struct confargs *)aux;
! 1090: struct pcibus_attach_args pba;
! 1091: volatile struct elroy_regs *r;
! 1092: const char *p = NULL, *q;
! 1093: int i;
! 1094:
! 1095: sc->sc_bt = ca->ca_iot;
! 1096: sc->sc_dmat = ca->ca_dmatag;
! 1097: if (bus_space_map(sc->sc_bt, ca->ca_hpa, ca->ca_hpasz, 0, &sc->sc_bh)) {
! 1098: printf(": can't map space\n");
! 1099: return;
! 1100: }
! 1101:
! 1102: sc->sc_regs = r = (void *)bus_space_vaddr(sc->sc_bt, sc->sc_bh);
! 1103: elroy_write32(&r->pci_cmdstat, htole32(PCI_COMMAND_IO_ENABLE |
! 1104: PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE));
! 1105:
! 1106: elroy_write32(&r->control, elroy_read32(&r->control) &
! 1107: ~htole32(ELROY_CONTROL_RF));
! 1108: for (i = 5000; i-- &&
! 1109: elroy_read32(&r->status) & htole32(ELROY_STATUS_RC); DELAY(10));
! 1110: if (i < 0) {
! 1111: printf(": reset failed; status %b\n",
! 1112: ELROY_STATUS_BITS, htole32(r->status));
! 1113: return;
! 1114: }
! 1115:
! 1116: q = "";
! 1117: sc->sc_ver = PCI_REVISION(letoh32(elroy_read32(&r->pci_class)));
! 1118: switch ((ca->ca_type.iodc_model << 4) |
! 1119: (ca->ca_type.iodc_revision >> 4)) {
! 1120: case 0x782:
! 1121: p = "Elroy";
! 1122: switch (sc->sc_ver) {
! 1123: default:
! 1124: q = "+";
! 1125: case 5: sc->sc_ver = 0x40; break;
! 1126: case 4: sc->sc_ver = 0x30; break;
! 1127: case 3: sc->sc_ver = 0x22; break;
! 1128: case 2: sc->sc_ver = 0x21; break;
! 1129: case 1: sc->sc_ver = 0x20; break;
! 1130: case 0: sc->sc_ver = 0x10; break;
! 1131: }
! 1132: break;
! 1133:
! 1134: case 0x783:
! 1135: p = "Mercury";
! 1136: break;
! 1137:
! 1138: case 0x784:
! 1139: p = "Quicksilver";
! 1140: break;
! 1141:
! 1142: default:
! 1143: p = "Mojo";
! 1144: break;
! 1145: }
! 1146:
! 1147: printf(": %s TR%d.%d%s", p, sc->sc_ver >> 4, sc->sc_ver & 0xf, q);
! 1148: apic_attach(sc);
! 1149: printf("\n");
! 1150:
! 1151: /* TODO reserve elroy's pci space ? */
! 1152:
! 1153: printf("lmm %llx/%llx gmm %llx/%llx wlm %llx/%llx wgm %llx/%llx io %llx/%llx eio %llx/%llx\n",
! 1154: letoh64(r->lmmio_base), letoh64(r->lmmio_mask),
! 1155: letoh64(r->gmmio_base), letoh64(r->gmmio_mask),
! 1156: letoh64(r->wlmmio_base), letoh64(r->wlmmio_mask),
! 1157: letoh64(r->wgmmio_base), letoh64(r->wgmmio_mask),
! 1158: letoh64(r->io_base), letoh64(r->io_mask),
! 1159: letoh64(r->eio_base), letoh64(r->eio_mask));
! 1160:
! 1161: /* XXX evil hack! */
! 1162: sc->sc_iobase = 0xfee00000;
! 1163:
! 1164: sc->sc_iot = elroy_iomemt;
! 1165: sc->sc_iot.hbt_cookie = sc;
! 1166: sc->sc_iot.hbt_map = elroy_iomap;
! 1167: sc->sc_iot.hbt_alloc = elroy_ioalloc;
! 1168: sc->sc_memt = elroy_iomemt;
! 1169: sc->sc_memt.hbt_cookie = sc;
! 1170: sc->sc_memt.hbt_map = elroy_memmap;
! 1171: sc->sc_memt.hbt_alloc = elroy_memalloc;
! 1172: sc->sc_pc = elroy_pc;
! 1173: sc->sc_pc._cookie = sc;
! 1174: sc->sc_dmatag = elroy_dmat;
! 1175: sc->sc_dmatag._cookie = sc;
! 1176:
! 1177: pba.pba_busname = "pci";
! 1178: pba.pba_iot = &sc->sc_iot;
! 1179: pba.pba_memt = &sc->sc_memt;
! 1180: pba.pba_dmat = &sc->sc_dmatag;
! 1181: pba.pba_pc = &sc->sc_pc;
! 1182: pba.pba_bridgetag = NULL;
! 1183: pba.pba_domain = pci_ndomains++;
! 1184: pba.pba_bus = 0; /* (letoh32(elroy_read32(&r->busnum)) & 0xff) >> 4; */
! 1185: config_found(self, &pba, elroyprint);
! 1186:
! 1187: /* enable interrupts now that all the devices are there */
! 1188: /* r->imr = sc->sc_imr; */
! 1189: }
CVSweb