1 /* $OpenBSD: mongoose.c,v 1.12 2003/05/11 19:41:09 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1998,1999 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Michael Shalayeff. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 35 #define MONGOOSE_DEBUG 9 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/reboot.h> 41 42 #include <machine/bus.h> 43 #include <machine/iomod.h> 44 #include <machine/autoconf.h> 45 46 #include <hppa/dev/cpudevs.h> 47 #include <hppa/dev/viper.h> 48 49 #include <dev/eisa/eisareg.h> 50 #include <dev/eisa/eisavar.h> 51 52 #include <dev/isa/isareg.h> 53 #include <dev/isa/isavar.h> 54 55 /* EISA Bus Adapter registers definitions */ 56 #define MONGOOSE_MONGOOSE 0x10000 57 struct mongoose_regs { 58 u_int8_t version; 59 u_int8_t lock; 60 u_int8_t liowait; 61 u_int8_t clock; 62 u_int8_t reserved[0xf000 - 4]; 63 u_int8_t intack; 64 }; 65 66 #define MONGOOSE_CTRL 0x00000 67 #define MONGOOSE_NINTS 16 68 struct mongoose_ctrl { 69 struct dma0 { 70 struct { 71 u_int32_t addr : 8; 72 u_int32_t count: 8; 73 } ch[4]; 74 u_int8_t command; 75 u_int8_t request; 76 u_int8_t mask_channel; 77 u_int8_t mode; 78 u_int8_t clr_byte_ptr; 79 u_int8_t master_clear; 80 u_int8_t mask_clear; 81 u_int8_t master_write; 82 u_int8_t pad[8]; 83 } dma0; 84 85 u_int8_t irr0; /* 0x20 */ 86 u_int8_t imr0; 87 u_int8_t iack; /* 0x22 -- 2 b2b reads generate 88 (e)isa Iack cycle & returns int level */ 89 u_int8_t pad0[29]; 90 91 struct timers { 92 u_int8_t sysclk; 93 u_int8_t refresh; 94 u_int8_t spkr; 95 u_int8_t ctrl; 96 u_int32_t pad; 97 } tmr[2]; /* 0x40 -- timers control */ 98 u_int8_t pad1[16]; 99 100 u_int16_t inmi; /* 0x60 NMI control */ 101 u_int8_t pad2[30]; 102 struct { 103 u_int8_t pad0; 104 u_int8_t ch2; 105 u_int8_t ch3; 106 u_int8_t ch1; 107 u_int8_t pad1; 108 u_int8_t pad2[3]; 109 u_int8_t ch0; 110 u_int8_t pad4; 111 u_int8_t ch6; 112 u_int8_t ch7; 113 u_int8_t ch5; 114 u_int8_t pad5[3]; 115 u_int8_t pad6[16]; 116 } pr; /* 0x80 */ 117 118 u_int8_t irr1; /* 0xa0 */ 119 u_int8_t imr1; 120 u_int8_t pad3[30]; 121 122 struct dma1 { 123 struct { 124 u_int32_t addr : 8; 125 u_int32_t pad0 : 8; 126 u_int32_t count: 8; 127 u_int32_t pad1 : 8; 128 } ch[4]; 129 u_int8_t command; 130 u_int8_t pad0; 131 u_int8_t request; 132 u_int8_t pad1; 133 u_int8_t mask_channel; 134 u_int8_t pad2; 135 u_int8_t mode; 136 u_int8_t pad3; 137 u_int8_t clr_byte_ptr; 138 u_int8_t pad4; 139 u_int8_t master_clear; 140 u_int8_t pad5; 141 u_int8_t mask_clear; 142 u_int8_t pad6; 143 u_int8_t master_write; 144 u_int8_t pad7; 145 } dma1; /* 0xc0 */ 146 147 u_int8_t master_req; /* 0xe0 master request register */ 148 u_int8_t pad4[31]; 149 150 u_int8_t pad5[0x3d0]; /* 0x4d0 */ 151 u_int8_t pic0; /* 0 - edge, 1 - level */ 152 u_int8_t pic1; 153 u_int8_t pad6[0x460]; 154 u_int8_t nmi; 155 u_int8_t nmi_ext; 156 #define MONGOOSE_NMI_BUSRESET 0x01 157 #define MONGOOSE_NMI_IOPORT_EN 0x02 158 #define MONGOOSE_NMI_EN 0x04 159 #define MONGOOSE_NMI_MTMO_EN 0x08 160 #define MONGOOSE_NMI_RES4 0x10 161 #define MONGOOSE_NMI_IOPORT_INT 0x20 162 #define MONGOOSE_NMI_MASTER_INT 0x40 163 #define MONGOOSE_NMI_INT 0x80 164 }; 165 166 #define MONGOOSE_IOMAP 0x100000 167 168 struct hppa_isa_iv { 169 const char *iv_name; 170 int (*iv_handler)(void *arg); 171 void *iv_arg; 172 int iv_pri; 173 174 struct evcnt iv_evcnt; 175 /* don't do sharing, we won't have many slots anyway 176 struct hppa_isa_iv *iv_next; 177 */ 178 }; 179 180 struct mongoose_softc { 181 struct device sc_dev; 182 void *sc_ih; 183 184 bus_space_tag_t sc_bt; 185 volatile struct mongoose_regs *sc_regs; 186 volatile struct mongoose_ctrl *sc_ctrl; 187 bus_addr_t sc_iomap; 188 189 /* interrupts section */ 190 struct hppa_eisa_chipset sc_ec; 191 struct hppa_isa_chipset sc_ic; 192 struct hppa_isa_iv sc_iv[MONGOOSE_NINTS]; 193 194 /* isa/eisa bus guts */ 195 struct hppa_bus_space_tag sc_eiot; 196 struct hppa_bus_space_tag sc_ememt; 197 struct hppa_bus_dma_tag sc_edmat; 198 struct hppa_bus_space_tag sc_iiot; 199 struct hppa_bus_space_tag sc_imemt; 200 struct hppa_bus_dma_tag sc_idmat; 201 }; 202 203 union mongoose_attach_args { 204 char *mongoose_name; 205 struct eisabus_attach_args mongoose_eisa; 206 struct isabus_attach_args mongoose_isa; 207 }; 208 209 int mgmatch(struct device *, void *, void *); 210 void mgattach(struct device *, struct device *, void *); 211 int mgprint(void *aux, const char *pnp); 212 213 struct cfattach mongoose_ca = { 214 sizeof(struct mongoose_softc), mgmatch, mgattach 215 }; 216 217 struct cfdriver mongoose_cd = { 218 NULL, "mg", DV_DULL 219 }; 220 221 /* TODO: DMA guts */ 222 223 void 224 mg_eisa_attach_hook(struct device *parent, struct device *self, 225 struct eisabus_attach_args *mg) 226 { 227 } 228 229 int 230 mg_intr_map(void *v, u_int irq, eisa_intr_handle_t *ehp) 231 { 232 *ehp = irq; 233 return 0; 234 } 235 236 const char * 237 mg_intr_string(void *v, int irq) 238 { 239 static char buf[16]; 240 241 snprintf(buf, sizeof buf, "isa irq %d", irq); 242 return buf; 243 } 244 245 void 246 mg_isa_attach_hook(struct device *parent, struct device *self, 247 struct isabus_attach_args *iba) 248 { 249 250 } 251 252 void * 253 mg_intr_establish(void *v, int irq, int type, int pri, 254 int (*handler)(void *), void *arg, char *name) 255 { 256 struct hppa_isa_iv *iv; 257 struct mongoose_softc *sc = v; 258 volatile u_int8_t *imr, *pic; 259 260 if (!sc || irq < 0 || irq >= MONGOOSE_NINTS || 261 (0 <= irq && irq < MONGOOSE_NINTS && sc->sc_iv[irq].iv_handler)) 262 return NULL; 263 264 if (type != IST_LEVEL && type != IST_EDGE) { 265 #ifdef DEBUG 266 printf("%s: bad interrupt level (%d)\n", sc->sc_dev.dv_xname, 267 type); 268 #endif 269 return NULL; 270 } 271 272 iv = &sc->sc_iv[irq]; 273 if (iv->iv_handler) { 274 #ifdef DEBUG 275 printf("%s: irq %d already established\n", sc->sc_dev.dv_xname, 276 irq); 277 #endif 278 return NULL; 279 } 280 281 iv->iv_name = name; 282 iv->iv_pri = pri; 283 iv->iv_handler = handler; 284 iv->iv_arg = arg; 285 286 if (irq < 8) { 287 imr = &sc->sc_ctrl->imr0; 288 pic = &sc->sc_ctrl->pic0; 289 } else { 290 imr = &sc->sc_ctrl->imr1; 291 pic = &sc->sc_ctrl->pic1; 292 irq -= 8; 293 } 294 295 *imr |= 1 << irq; 296 *pic |= (type == IST_LEVEL) << irq; 297 298 /* TODO: ack it? */ 299 300 return iv; 301 } 302 303 void 304 mg_intr_disestablish(void *v, void *cookie) 305 { 306 struct hppa_isa_iv *iv = cookie; 307 struct mongoose_softc *sc = v; 308 int irq = iv - sc->sc_iv; 309 volatile u_int8_t *imr; 310 311 if (!sc || !cookie) 312 return; 313 314 if (irq < 8) 315 imr = &sc->sc_ctrl->imr0; 316 else 317 imr = &sc->sc_ctrl->imr1; 318 *imr &= ~(1 << irq); 319 /* TODO: ack it? */ 320 321 iv->iv_handler = NULL; 322 } 323 324 int 325 mg_intr_check(void *v, int irq, int type) 326 { 327 return 0; 328 } 329 330 int 331 mg_intr(void *v) 332 { 333 struct mongoose_softc *sc = v; 334 struct hppa_isa_iv *iv; 335 int s, irq = 0; 336 337 iv = &sc->sc_iv[irq]; 338 s = splraise(iv->iv_pri); 339 (iv->iv_handler)(iv->iv_arg); 340 splx(s); 341 342 return 0; 343 } 344 345 int 346 mg_eisa_iomap(void *v, bus_addr_t addr, bus_size_t size, int cacheable, 347 bus_space_handle_t *bshp) 348 { 349 struct mongoose_softc *sc = v; 350 351 /* see if it's ISA space we are mapping */ 352 if (0x100 <= addr && addr < 0x400) { 353 #define TOISA(a) ((((a) & 0x3f8) << 9) + ((a) & 7)) 354 size = TOISA(addr + size) - TOISA(addr); 355 addr = TOISA(addr); 356 } 357 358 return (sc->sc_bt->hbt_map)(NULL, sc->sc_iomap + addr, size, 359 cacheable, bshp); 360 } 361 362 int 363 mg_eisa_memmap(void *v, bus_addr_t addr, bus_size_t size, int cacheable, 364 bus_space_handle_t *bshp) 365 { 366 /* TODO: eisa memory map */ 367 return -1; 368 } 369 370 void 371 mg_eisa_memunmap(void *v, bus_space_handle_t bsh, bus_size_t size) 372 { 373 /* TODO: eisa memory unmap */ 374 } 375 376 void 377 mg_isa_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op) 378 { 379 sync_caches(); 380 } 381 382 u_int16_t 383 mg_isa_r2(void *v, bus_space_handle_t h, bus_size_t o) 384 { 385 register u_int16_t r = *((volatile u_int16_t *)(h + o)); 386 return letoh16(r); 387 } 388 389 u_int32_t 390 mg_isa_r4(void *v, bus_space_handle_t h, bus_size_t o) 391 { 392 register u_int32_t r = *((volatile u_int32_t *)(h + o)); 393 return letoh32(r); 394 } 395 396 void 397 mg_isa_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv) 398 { 399 *((volatile u_int16_t *)(h + o)) = htole16(vv); 400 } 401 402 void 403 mg_isa_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv) 404 { 405 *((volatile u_int32_t *)(h + o)) = htole32(vv); 406 } 407 408 void 409 mg_isa_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 410 { 411 h += o; 412 while (c--) 413 *(a++) = letoh16(*(volatile u_int16_t *)h); 414 } 415 416 void 417 mg_isa_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 418 { 419 h += o; 420 while (c--) 421 *(a++) = letoh32(*(volatile u_int32_t *)h); 422 } 423 424 void 425 mg_isa_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 426 { 427 register u_int16_t r; 428 h += o; 429 while (c--) { 430 r = *(a++); 431 *(volatile u_int16_t *)h = htole16(r); 432 } 433 } 434 435 void 436 mg_isa_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 437 { 438 register u_int32_t r; 439 h += o; 440 while (c--) { 441 r = *(a++); 442 *(volatile u_int32_t *)h = htole32(r); 443 } 444 } 445 446 void 447 mg_isa_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 448 { 449 vv = htole16(vv); 450 h += o; 451 while (c--) 452 *(volatile u_int16_t *)h = vv; 453 } 454 455 void 456 mg_isa_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 457 { 458 vv = htole32(vv); 459 h += o; 460 while (c--) 461 *(volatile u_int32_t *)h = vv; 462 } 463 464 void 465 mg_isa_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 466 { 467 register u_int16_t r; 468 h += o; 469 while (c--) { 470 r = *((volatile u_int16_t *)h)++; 471 *(a++) = letoh16(r); 472 } 473 } 474 475 void 476 mg_isa_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 477 { 478 register u_int32_t r; 479 h += o; 480 while (c--) { 481 r = *((volatile u_int32_t *)h)++; 482 *(a++) = letoh32(r); 483 } 484 } 485 486 void 487 mg_isa_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 488 { 489 register u_int16_t r; 490 h += o; 491 while (c--) { 492 r = *(a++); 493 *((volatile u_int16_t *)h)++ = htole16(r); 494 } 495 } 496 497 void 498 mg_isa_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 499 { 500 register u_int32_t r; 501 h += o; 502 while (c--) { 503 r = *(a++); 504 *((volatile u_int32_t *)h)++ = htole32(r); 505 } 506 } 507 508 void 509 mg_isa_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 510 { 511 vv = htole16(vv); 512 h += o; 513 while (c--) 514 *((volatile u_int16_t *)h)++ = vv; 515 } 516 517 void 518 mg_isa_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 519 { 520 vv = htole32(vv); 521 h += o; 522 while (c--) 523 *((volatile u_int32_t *)h)++ = vv; 524 } 525 526 int 527 mgmatch(parent, cfdata, aux) 528 struct device *parent; 529 void *cfdata; 530 void *aux; 531 { 532 register struct confargs *ca = aux; 533 /* struct cfdata *cf = cfdata; */ 534 bus_space_handle_t ioh; 535 536 if (ca->ca_type.iodc_type != HPPA_TYPE_BHA || 537 ca->ca_type.iodc_sv_model != HPPA_BHA_EISA) 538 return 0; 539 540 if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE, IOMOD_HPASIZE, 541 0, &ioh)) 542 return 0; 543 544 /* XXX check EISA signature */ 545 546 bus_space_unmap(ca->ca_iot, ioh, IOMOD_HPASIZE); 547 548 return 1; 549 } 550 551 void 552 mgattach(parent, self, aux) 553 struct device *parent; 554 struct device *self; 555 void *aux; 556 { 557 register struct confargs *ca = aux; 558 register struct mongoose_softc *sc = (struct mongoose_softc *)self; 559 struct hppa_bus_space_tag *bt; 560 union mongoose_attach_args ea; 561 char brid[EISA_IDSTRINGLEN]; 562 563 sc->sc_bt = ca->ca_iot; 564 sc->sc_iomap = ca->ca_hpa; 565 sc->sc_regs = (struct mongoose_regs *)(ca->ca_hpa + MONGOOSE_MONGOOSE); 566 sc->sc_ctrl = (struct mongoose_ctrl *)(ca->ca_hpa + MONGOOSE_CTRL); 567 568 viper_eisa_en(); 569 570 /* BUS RESET */ 571 sc->sc_ctrl->nmi_ext = MONGOOSE_NMI_BUSRESET; 572 DELAY(1); 573 sc->sc_ctrl->nmi_ext = 0; 574 DELAY(100); 575 576 /* determine eisa board id */ 577 { 578 u_int8_t id[4], *p; 579 p = (u_int8_t *)(ca->ca_hpa + EISA_SLOTOFF_VID); 580 id[0] = *p++; 581 id[1] = *p++; 582 id[2] = *p++; 583 id[3] = *p++; 584 585 brid[0] = EISA_VENDID_0(id); 586 brid[1] = EISA_VENDID_1(id); 587 brid[2] = EISA_VENDID_2(id); 588 brid[3] = EISA_PRODID_0(id + 2); 589 brid[4] = EISA_PRODID_1(id + 2); 590 brid[5] = EISA_PRODID_2(id + 2); 591 brid[6] = EISA_PRODID_3(id + 2); 592 brid[7] = '\0'; 593 } 594 595 printf (": %s rev %d, %d MHz\n", brid, sc->sc_regs->version, 596 (sc->sc_regs->clock? 33 : 25)); 597 sc->sc_regs->liowait = 1; /* disable isa wait states */ 598 sc->sc_regs->lock = 1; /* bus unlock */ 599 600 /* attach EISA */ 601 sc->sc_ec.ec_v = sc; 602 sc->sc_ec.ec_attach_hook = mg_eisa_attach_hook; 603 sc->sc_ec.ec_intr_establish = mg_intr_establish; 604 sc->sc_ec.ec_intr_disestablish = mg_intr_disestablish; 605 sc->sc_ec.ec_intr_string = mg_intr_string; 606 sc->sc_ec.ec_intr_map = mg_intr_map; 607 /* inherit the bus tags for eisa from the mainbus */ 608 bt = &sc->sc_eiot; 609 bcopy(ca->ca_iot, bt, sizeof(*bt)); 610 bt->hbt_cookie = sc; 611 bt->hbt_map = mg_eisa_iomap; 612 #define R(n) bt->__CONCAT(hbt_,n) = &__CONCAT(mg_isa_,n) 613 /* R(barrier); */ 614 R(r2); R(r4); R(w2); R(w4); 615 R(rm_2);R(rm_4);R(wm_2);R(wm_4);R(sm_2);R(sm_4); 616 R(rr_2);R(rr_4);R(wr_2);R(wr_4);R(sr_2);R(sr_4); 617 618 bt = &sc->sc_ememt; 619 bcopy(ca->ca_iot, bt, sizeof(*bt)); 620 bt->hbt_cookie = sc; 621 bt->hbt_map = mg_eisa_memmap; 622 bt->hbt_unmap = mg_eisa_memunmap; 623 /* attachment guts */ 624 ea.mongoose_eisa.eba_busname = "eisa"; 625 ea.mongoose_eisa.eba_iot = &sc->sc_eiot; 626 ea.mongoose_eisa.eba_memt = &sc->sc_ememt; 627 ea.mongoose_eisa.eba_dmat = NULL /* &sc->sc_edmat */; 628 ea.mongoose_eisa.eba_ec = &sc->sc_ec; 629 config_found(self, &ea.mongoose_eisa, mgprint); 630 631 sc->sc_ic.ic_v = sc; 632 sc->sc_ic.ic_attach_hook = mg_isa_attach_hook; 633 sc->sc_ic.ic_intr_establish = mg_intr_establish; 634 sc->sc_ic.ic_intr_disestablish = mg_intr_disestablish; 635 sc->sc_ic.ic_intr_check = mg_intr_check; 636 /* inherit the bus tags for isa from the eisa */ 637 bt = &sc->sc_imemt; 638 bcopy(&sc->sc_ememt, bt, sizeof(*bt)); 639 bt = &sc->sc_iiot; 640 bcopy(&sc->sc_eiot, bt, sizeof(*bt)); 641 /* TODO: DMA tags */ 642 /* attachment guts */ 643 ea.mongoose_isa.iba_busname = "isa"; 644 ea.mongoose_isa.iba_iot = &sc->sc_iiot; 645 ea.mongoose_isa.iba_memt = &sc->sc_imemt; 646 #if NISADMA > 0 647 ea.mongoose_isa.iba_dmat = &sc->sc_idmat; 648 #endif 649 ea.mongoose_isa.iba_ic = &sc->sc_ic; 650 config_found(self, &ea.mongoose_isa, mgprint); 651 #undef R 652 653 /* attach interrupt */ 654 sc->sc_ih = cpu_intr_establish(IPL_HIGH, ca->ca_irq, 655 mg_intr, sc, &sc->sc_dev); 656 } 657 658 int 659 mgprint(aux, pnp) 660 void *aux; 661 const char *pnp; 662 { 663 union mongoose_attach_args *ea = aux; 664 665 if (pnp) 666 printf ("%s at %s", ea->mongoose_name, pnp); 667 668 return (UNCONF); 669 } 670 671