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