1 /* $OpenBSD: elroy.c,v 1.5 2009/03/30 21:24:57 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 void * 350 elroy_vaddr(void *v, bus_space_handle_t h) 351 { 352 return ((void *)h); 353 } 354 355 u_int8_t 356 elroy_r1(void *v, bus_space_handle_t h, bus_size_t o) 357 { 358 h += o; 359 return *(volatile u_int8_t *)h; 360 } 361 362 u_int16_t 363 elroy_r2(void *v, bus_space_handle_t h, bus_size_t o) 364 { 365 volatile u_int16_t *p; 366 367 h += o; 368 p = (volatile u_int16_t *)h; 369 return (letoh16(*p)); 370 } 371 372 u_int32_t 373 elroy_r4(void *v, bus_space_handle_t h, bus_size_t o) 374 { 375 u_int32_t data; 376 377 h += o; 378 data = *(volatile u_int32_t *)h; 379 return (letoh32(data)); 380 } 381 382 u_int64_t 383 elroy_r8(void *v, bus_space_handle_t h, bus_size_t o) 384 { 385 u_int64_t data; 386 387 h += o; 388 data = *(volatile u_int64_t *)h; 389 return (letoh64(data)); 390 } 391 392 void 393 elroy_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv) 394 { 395 h += o; 396 *(volatile u_int8_t *)h = vv; 397 } 398 399 void 400 elroy_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv) 401 { 402 volatile u_int16_t *p; 403 404 h += o; 405 p = (volatile u_int16_t *)h; 406 *p = htole16(vv); 407 } 408 409 void 410 elroy_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv) 411 { 412 h += o; 413 vv = htole32(vv); 414 *(volatile u_int32_t *)h = vv; 415 } 416 417 void 418 elroy_w8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv) 419 { 420 h += o; 421 *(volatile u_int64_t *)h = htole64(vv); 422 } 423 424 425 void 426 elroy_rm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c) 427 { 428 volatile u_int8_t *p; 429 430 h += o; 431 p = (volatile u_int8_t *)h; 432 while (c--) 433 *a++ = *p; 434 } 435 436 void 437 elroy_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 438 { 439 volatile u_int16_t *p; 440 441 h += o; 442 p = (volatile u_int16_t *)h; 443 while (c--) 444 *a++ = letoh16(*p); 445 } 446 447 void 448 elroy_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 449 { 450 volatile u_int32_t *p; 451 452 h += o; 453 p = (volatile u_int32_t *)h; 454 while (c--) 455 *a++ = letoh32(*p); 456 } 457 458 void 459 elroy_rm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c) 460 { 461 volatile u_int64_t *p; 462 463 h += o; 464 p = (volatile u_int64_t *)h; 465 while (c--) 466 *a++ = letoh64(*p); 467 } 468 469 void 470 elroy_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c) 471 { 472 volatile u_int8_t *p; 473 474 h += o; 475 p = (volatile u_int8_t *)h; 476 while (c--) 477 *p = *a++; 478 } 479 480 void 481 elroy_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 482 { 483 volatile u_int16_t *p; 484 485 h += o; 486 p = (volatile u_int16_t *)h; 487 while (c--) 488 *p = htole16(*a++); 489 } 490 491 void 492 elroy_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 493 { 494 volatile u_int32_t *p; 495 496 h += o; 497 p = (volatile u_int32_t *)h; 498 while (c--) 499 *p = htole32(*a++); 500 } 501 502 void 503 elroy_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c) 504 { 505 volatile u_int64_t *p; 506 507 h += o; 508 p = (volatile u_int64_t *)h; 509 while (c--) 510 *p = htole64(*a++); 511 } 512 513 void 514 elroy_sm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c) 515 { 516 volatile u_int8_t *p; 517 518 h += o; 519 p = (volatile u_int8_t *)h; 520 while (c--) 521 *p = vv; 522 } 523 524 void 525 elroy_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 526 { 527 volatile u_int16_t *p; 528 529 h += o; 530 p = (volatile u_int16_t *)h; 531 vv = htole16(vv); 532 while (c--) 533 *p = vv; 534 } 535 536 void 537 elroy_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 538 { 539 volatile u_int32_t *p; 540 541 h += o; 542 p = (volatile u_int32_t *)h; 543 vv = htole32(vv); 544 while (c--) 545 *p = vv; 546 } 547 548 void 549 elroy_sm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c) 550 { 551 volatile u_int64_t *p; 552 553 h += o; 554 p = (volatile u_int64_t *)h; 555 vv = htole64(vv); 556 while (c--) 557 *p = vv; 558 } 559 560 void 561 elroy_rrm_2(void *v, bus_space_handle_t h, bus_size_t o, 562 u_int8_t *a, bus_size_t c) 563 { 564 volatile u_int16_t *p, *q = (u_int16_t *)a; 565 566 h += o; 567 p = (volatile u_int16_t *)h; 568 c /= 2; 569 while (c--) 570 *q++ = *p; 571 } 572 573 void 574 elroy_rrm_4(void *v, bus_space_handle_t h, bus_size_t o, 575 u_int8_t *a, bus_size_t c) 576 { 577 volatile u_int32_t *p, *q = (u_int32_t *)a; 578 579 h += o; 580 p = (volatile u_int32_t *)h; 581 c /= 4; 582 while (c--) 583 *q++ = *p; 584 } 585 586 void 587 elroy_rrm_8(void *v, bus_space_handle_t h, bus_size_t o, 588 u_int8_t *a, bus_size_t c) 589 { 590 volatile u_int64_t *p, *q = (u_int64_t *)a; 591 592 h += o; 593 p = (volatile u_int64_t *)h; 594 c /= 8; 595 while (c--) 596 *q++ = *p; 597 } 598 599 void 600 elroy_wrm_2(void *v, bus_space_handle_t h, bus_size_t o, 601 const u_int8_t *a, bus_size_t c) 602 { 603 volatile u_int16_t *p; 604 const u_int16_t *q = (const u_int16_t *)a; 605 606 h += o; 607 p = (volatile u_int16_t *)h; 608 c /= 2; 609 while (c--) 610 *p = *q++; 611 } 612 613 void 614 elroy_wrm_4(void *v, bus_space_handle_t h, bus_size_t o, 615 const u_int8_t *a, bus_size_t c) 616 { 617 volatile u_int32_t *p; 618 const u_int32_t *q = (const u_int32_t *)a; 619 620 h += o; 621 p = (volatile u_int32_t *)h; 622 c /= 4; 623 while (c--) 624 *p = *q++; 625 } 626 627 void 628 elroy_wrm_8(void *v, bus_space_handle_t h, bus_size_t o, 629 const u_int8_t *a, bus_size_t c) 630 { 631 volatile u_int64_t *p; 632 const u_int64_t *q = (const u_int64_t *)a; 633 634 h += o; 635 p = (volatile u_int64_t *)h; 636 c /= 8; 637 while (c--) 638 *p = *q++; 639 } 640 641 void 642 elroy_rr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c) 643 { 644 volatile u_int8_t *p; 645 646 h += o; 647 p = (volatile u_int8_t *)h; 648 while (c--) 649 *a++ = *p++; 650 } 651 652 void 653 elroy_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 654 { 655 volatile u_int16_t *p, data; 656 657 h += o; 658 p = (volatile u_int16_t *)h; 659 while (c--) { 660 data = *p++; 661 *a++ = letoh16(data); 662 } 663 } 664 665 void 666 elroy_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 667 { 668 volatile u_int32_t *p, data; 669 670 h += o; 671 p = (volatile u_int32_t *)h; 672 while (c--) { 673 data = *p++; 674 *a++ = letoh32(data); 675 } 676 } 677 678 void 679 elroy_rr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c) 680 { 681 volatile u_int64_t *p, data; 682 683 h += o; 684 p = (volatile u_int64_t *)h; 685 while (c--) { 686 data = *p++; 687 *a++ = letoh64(data); 688 } 689 } 690 691 void 692 elroy_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c) 693 { 694 volatile u_int8_t *p; 695 696 h += o; 697 p = (volatile u_int8_t *)h; 698 while (c--) 699 *p++ = *a++; 700 } 701 702 void 703 elroy_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 704 { 705 volatile u_int16_t *p, data; 706 707 h += o; 708 p = (volatile u_int16_t *)h; 709 while (c--) { 710 data = *a++; 711 *p++ = htole16(data); 712 } 713 } 714 715 void 716 elroy_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 717 { 718 volatile u_int32_t *p, data; 719 720 h += o; 721 p = (volatile u_int32_t *)h; 722 while (c--) { 723 data = *a++; 724 *p++ = htole32(data); 725 } 726 } 727 728 void 729 elroy_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c) 730 { 731 volatile u_int64_t *p, data; 732 733 h += o; 734 p = (volatile u_int64_t *)h; 735 while (c--) { 736 data = *a++; 737 *p++ = htole64(data); 738 } 739 } 740 741 void 742 elroy_rrr_2(void *v, bus_space_handle_t h, bus_size_t o, 743 u_int8_t *a, bus_size_t c) 744 { 745 volatile u_int16_t *p, *q = (u_int16_t *)a; 746 747 c /= 2; 748 h += o; 749 p = (volatile u_int16_t *)h; 750 while (c--) 751 *q++ = *p++; 752 } 753 754 void 755 elroy_rrr_4(void *v, bus_space_handle_t h, bus_size_t o, 756 u_int8_t *a, bus_size_t c) 757 { 758 volatile u_int32_t *p, *q = (u_int32_t *)a; 759 760 c /= 4; 761 h += o; 762 p = (volatile u_int32_t *)h; 763 while (c--) 764 *q++ = *p++; 765 } 766 767 void 768 elroy_rrr_8(void *v, bus_space_handle_t h, bus_size_t o, 769 u_int8_t *a, bus_size_t c) 770 { 771 volatile u_int64_t *p, *q = (u_int64_t *)a; 772 773 c /= 8; 774 h += o; 775 p = (volatile u_int64_t *)h; 776 while (c--) 777 *q++ = *p++; 778 } 779 780 void 781 elroy_wrr_2(void *v, bus_space_handle_t h, bus_size_t o, 782 const u_int8_t *a, bus_size_t c) 783 { 784 volatile u_int16_t *p; 785 const u_int16_t *q = (u_int16_t *)a; 786 787 c /= 2; 788 h += o; 789 p = (volatile u_int16_t *)h; 790 while (c--) 791 *p++ = *q++; 792 } 793 794 void 795 elroy_wrr_4(void *v, bus_space_handle_t h, bus_size_t o, 796 const u_int8_t *a, bus_size_t c) 797 { 798 volatile u_int32_t *p; 799 const u_int32_t *q = (u_int32_t *)a; 800 801 c /= 4; 802 h += o; 803 p = (volatile u_int32_t *)h; 804 while (c--) 805 *p++ = *q++; 806 } 807 808 void 809 elroy_wrr_8(void *v, bus_space_handle_t h, bus_size_t o, 810 const u_int8_t *a, bus_size_t c) 811 { 812 volatile u_int64_t *p; 813 const u_int64_t *q = (u_int64_t *)a; 814 815 c /= 8; 816 h += o; 817 p = (volatile u_int64_t *)h; 818 while (c--) 819 *p++ = *q++; 820 } 821 822 void 823 elroy_sr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c) 824 { 825 volatile u_int8_t *p; 826 827 h += o; 828 p = (volatile u_int8_t *)h; 829 while (c--) 830 *p++ = vv; 831 } 832 833 void 834 elroy_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 835 { 836 volatile u_int16_t *p; 837 838 h += o; 839 vv = htole16(vv); 840 p = (volatile u_int16_t *)h; 841 while (c--) 842 *p++ = vv; 843 } 844 845 void 846 elroy_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 847 { 848 volatile u_int32_t *p; 849 850 h += o; 851 vv = htole32(vv); 852 p = (volatile u_int32_t *)h; 853 while (c--) 854 *p++ = vv; 855 } 856 857 void 858 elroy_sr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c) 859 { 860 volatile u_int64_t *p; 861 862 h += o; 863 vv = htole64(vv); 864 p = (volatile u_int64_t *)h; 865 while (c--) 866 *p++ = vv; 867 } 868 869 void 870 elroy_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1, 871 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 872 { 873 while (c--) 874 elroy_w1(v, h1, o1++, elroy_r1(v, h2, o2++)); 875 } 876 877 void 878 elroy_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1, 879 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 880 { 881 while (c--) { 882 elroy_w2(v, h1, o1, elroy_r2(v, h2, o2)); 883 o1 += 2; 884 o2 += 2; 885 } 886 } 887 888 void 889 elroy_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1, 890 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 891 { 892 while (c--) { 893 elroy_w4(v, h1, o1, elroy_r4(v, h2, o2)); 894 o1 += 4; 895 o2 += 4; 896 } 897 } 898 899 void 900 elroy_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1, 901 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 902 { 903 while (c--) { 904 elroy_w8(v, h1, o1, elroy_r8(v, h2, o2)); 905 o1 += 8; 906 o2 += 8; 907 } 908 } 909 910 const struct hppa_bus_space_tag elroy_iomemt = { 911 NULL, 912 913 NULL, elroy_unmap, elroy_subregion, NULL, elroy_free, 914 elroy_barrier, elroy_vaddr, 915 elroy_r1, elroy_r2, elroy_r4, elroy_r8, 916 elroy_w1, elroy_w2, elroy_w4, elroy_w8, 917 elroy_rm_1, elroy_rm_2, elroy_rm_4, elroy_rm_8, 918 elroy_wm_1, elroy_wm_2, elroy_wm_4, elroy_wm_8, 919 elroy_sm_1, elroy_sm_2, elroy_sm_4, elroy_sm_8, 920 elroy_rrm_2, elroy_rrm_4, elroy_rrm_8, 921 elroy_wrm_2, elroy_wrm_4, elroy_wrm_8, 922 elroy_rr_1, elroy_rr_2, elroy_rr_4, elroy_rr_8, 923 elroy_wr_1, elroy_wr_2, elroy_wr_4, elroy_wr_8, 924 elroy_rrr_2, elroy_rrr_4, elroy_rrr_8, 925 elroy_wrr_2, elroy_wrr_4, elroy_wrr_8, 926 elroy_sr_1, elroy_sr_2, elroy_sr_4, elroy_sr_8, 927 elroy_cp_1, elroy_cp_2, elroy_cp_4, elroy_cp_8 928 }; 929 930 int 931 elroy_dmamap_create(void *v, bus_size_t size, int nsegments, 932 bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) 933 { 934 struct elroy_softc *sc = v; 935 936 /* TODO check the addresses, boundary, enable dma */ 937 938 return (bus_dmamap_create(sc->sc_dmat, size, nsegments, 939 maxsegsz, boundary, flags, dmamp)); 940 } 941 942 void 943 elroy_dmamap_destroy(void *v, bus_dmamap_t map) 944 { 945 struct elroy_softc *sc = v; 946 947 bus_dmamap_destroy(sc->sc_dmat, map); 948 } 949 950 int 951 elroy_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size, 952 struct proc *p, int flags) 953 { 954 struct elroy_softc *sc = v; 955 956 return (bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags)); 957 } 958 959 int 960 elroy_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags) 961 { 962 struct elroy_softc *sc = v; 963 964 return (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags)); 965 } 966 967 int 968 elroy_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags) 969 { 970 struct elroy_softc *sc = v; 971 972 return (bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags)); 973 } 974 975 int 976 elroy_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs, 977 int nsegs, bus_size_t size, int flags) 978 { 979 struct elroy_softc *sc = v; 980 981 return (bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags)); 982 } 983 984 void 985 elroy_dmamap_unload(void *v, bus_dmamap_t map) 986 { 987 struct elroy_softc *sc = v; 988 989 bus_dmamap_unload(sc->sc_dmat, map); 990 } 991 992 void 993 elroy_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off, 994 bus_size_t len, int ops) 995 { 996 struct elroy_softc *sc = v; 997 998 bus_dmamap_sync(sc->sc_dmat, map, off, len, ops); 999 } 1000 1001 int 1002 elroy_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment, 1003 bus_size_t boundary, bus_dma_segment_t *segs, 1004 int nsegs, int *rsegs, int flags) 1005 { 1006 struct elroy_softc *sc = v; 1007 1008 return (bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary, 1009 segs, nsegs, rsegs, flags)); 1010 } 1011 1012 void 1013 elroy_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs) 1014 { 1015 struct elroy_softc *sc = v; 1016 1017 bus_dmamem_free(sc->sc_dmat, segs, nsegs); 1018 } 1019 1020 int 1021 elroy_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size, 1022 caddr_t *kvap, int flags) 1023 { 1024 struct elroy_softc *sc = v; 1025 1026 return (bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags)); 1027 } 1028 1029 void 1030 elroy_dmamem_unmap(void *v, caddr_t kva, size_t size) 1031 { 1032 struct elroy_softc *sc = v; 1033 1034 bus_dmamem_unmap(sc->sc_dmat, kva, size); 1035 } 1036 1037 paddr_t 1038 elroy_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off, 1039 int prot, int flags) 1040 { 1041 struct elroy_softc *sc = v; 1042 1043 return (bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags)); 1044 } 1045 1046 const struct hppa_bus_dma_tag elroy_dmat = { 1047 NULL, 1048 elroy_dmamap_create, elroy_dmamap_destroy, 1049 elroy_dmamap_load, elroy_dmamap_load_mbuf, 1050 elroy_dmamap_load_uio, elroy_dmamap_load_raw, 1051 elroy_dmamap_unload, elroy_dmamap_sync, 1052 1053 elroy_dmamem_alloc, elroy_dmamem_free, elroy_dmamem_map, 1054 elroy_dmamem_unmap, elroy_dmamem_mmap 1055 }; 1056 1057 const struct hppa_pci_chipset_tag elroy_pc = { 1058 NULL, 1059 elroy_attach_hook, elroy_maxdevs, elroy_make_tag, elroy_decompose_tag, 1060 elroy_conf_read, elroy_conf_write, 1061 apic_intr_map, apic_intr_string, 1062 apic_intr_establish, apic_intr_disestablish, 1063 #if NCARDBUS > 0 1064 elroy_alloc_parent 1065 #else 1066 NULL 1067 #endif 1068 }; 1069 1070 int 1071 elroy_print(void *aux, const char *pnp) 1072 { 1073 struct pcibus_attach_args *pba = aux; 1074 1075 if (pnp) 1076 printf("%s at %s\n", pba->pba_busname, pnp); 1077 return (UNCONF); 1078 } 1079 1080 void 1081 elroy_attach(struct device *parent, struct device *self, void *aux) 1082 { 1083 struct elroy_softc *sc = (struct elroy_softc *)self; 1084 struct confargs *ca = (struct confargs *)aux; 1085 struct pcibus_attach_args pba; 1086 volatile struct elroy_regs *r; 1087 const char *p = NULL, *q; 1088 int i; 1089 1090 sc->sc_hpa = ca->ca_hpa; 1091 sc->sc_bt = ca->ca_iot; 1092 sc->sc_dmat = ca->ca_dmatag; 1093 if (bus_space_map(sc->sc_bt, ca->ca_hpa, ca->ca_hpasz, 0, &sc->sc_bh)) { 1094 printf(": can't map space\n"); 1095 return; 1096 } 1097 1098 sc->sc_regs = r = bus_space_vaddr(sc->sc_bt, sc->sc_bh); 1099 elroy_write32(&r->pci_cmdstat, htole32(PCI_COMMAND_IO_ENABLE | 1100 PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)); 1101 1102 elroy_write32(&r->control, elroy_read32(&r->control) & 1103 ~htole32(ELROY_CONTROL_RF)); 1104 for (i = 5000; i-- && 1105 elroy_read32(&r->status) & htole32(ELROY_STATUS_RC); DELAY(10)); 1106 if (i < 0) { 1107 printf(": reset failed; status %b\n", 1108 ELROY_STATUS_BITS, htole32(r->status)); 1109 return; 1110 } 1111 1112 q = ""; 1113 sc->sc_ver = PCI_REVISION(letoh32(elroy_read32(&r->pci_class))); 1114 switch ((ca->ca_type.iodc_model << 4) | 1115 (ca->ca_type.iodc_revision >> 4)) { 1116 case 0x782: 1117 p = "Elroy"; 1118 switch (sc->sc_ver) { 1119 default: 1120 q = "+"; 1121 case 5: sc->sc_ver = 0x40; break; 1122 case 4: sc->sc_ver = 0x30; break; 1123 case 3: sc->sc_ver = 0x22; break; 1124 case 2: sc->sc_ver = 0x21; break; 1125 case 1: sc->sc_ver = 0x20; break; 1126 case 0: sc->sc_ver = 0x10; break; 1127 } 1128 break; 1129 1130 case 0x783: 1131 p = "Mercury"; 1132 break; 1133 1134 case 0x784: 1135 p = "Quicksilver"; 1136 break; 1137 1138 default: 1139 p = "Mojo"; 1140 break; 1141 } 1142 1143 printf(": %s TR%d.%d%s", p, sc->sc_ver >> 4, sc->sc_ver & 0xf, q); 1144 apic_attach(sc); 1145 printf("\n"); 1146 1147 elroy_write32(&r->imask, htole32(0xffffffff << 30)); 1148 elroy_write32(&r->ibase, htole32(ELROY_BASE_RE)); 1149 1150 /* TODO reserve elroy's pci space ? */ 1151 1152 #if 0 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 #endif 1161 1162 /* XXX evil hack! */ 1163 sc->sc_iobase = 0xfee00000; 1164 1165 sc->sc_iot = elroy_iomemt; 1166 sc->sc_iot.hbt_cookie = sc; 1167 sc->sc_iot.hbt_map = elroy_iomap; 1168 sc->sc_iot.hbt_alloc = elroy_ioalloc; 1169 sc->sc_memt = elroy_iomemt; 1170 sc->sc_memt.hbt_cookie = sc; 1171 sc->sc_memt.hbt_map = elroy_memmap; 1172 sc->sc_memt.hbt_alloc = elroy_memalloc; 1173 sc->sc_pc = elroy_pc; 1174 sc->sc_pc._cookie = sc; 1175 sc->sc_dmatag = elroy_dmat; 1176 sc->sc_dmatag._cookie = sc; 1177 1178 bzero(&pba, sizeof(pba)); 1179 pba.pba_busname = "pci"; 1180 pba.pba_iot = &sc->sc_iot; 1181 pba.pba_memt = &sc->sc_memt; 1182 pba.pba_dmat = &sc->sc_dmatag; 1183 pba.pba_pc = &sc->sc_pc; 1184 pba.pba_domain = pci_ndomains++; 1185 pba.pba_bus = 0; /* (letoh32(elroy_read32(&r->busnum)) & 0xff) >> 4; */ 1186 config_found(self, &pba, elroy_print); 1187 } 1188