1 /* $OpenBSD: mongoose.c,v 1.23 2022/03/13 08:04:38 mpi Exp $ */ 2 3 /* 4 * Copyright (c) 1998-2003 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/device.h> 32 #include <sys/reboot.h> 33 34 #include <machine/bus.h> 35 #include <machine/iomod.h> 36 #include <machine/autoconf.h> 37 38 #include <hppa/dev/cpudevs.h> 39 #include <hppa/dev/viper.h> 40 41 #include <dev/eisa/eisareg.h> 42 #include <dev/eisa/eisavar.h> 43 44 #include <dev/isa/isareg.h> 45 #include <dev/isa/isavar.h> 46 47 #include <hppa/dev/mongoosereg.h> 48 #include <hppa/dev/mongoosevar.h> 49 50 void mgattach_gedoens(struct device *, struct device *, void *); 51 int mgmatch_gedoens(struct device *, void *, void *); 52 53 const struct cfattach mg_gedoens_ca = { 54 sizeof(struct mongoose_softc), mgmatch_gedoens, mgattach_gedoens 55 }; 56 57 struct cfdriver mongoose_cd = { 58 NULL, "mongoose", DV_DULL 59 }; 60 61 void mg_eisa_attach_hook(struct device *parent, 62 struct device *self, 63 struct eisabus_attach_args *mg); 64 int mg_intr_map(void *v, u_int irq, eisa_intr_handle_t *ehp); 65 const char *mg_intr_string(void *v, int irq); 66 void mg_isa_attach_hook(struct device *parent, 67 struct device *self, 68 struct isabus_attach_args *iba); 69 void *mg_intr_establish(void *v, int irq, int type, int pri, 70 int (*handler)(void *), void *arg, const char *name); 71 void mg_intr_disestablish(void *v, void *cookie); 72 int mg_intr_check(void *v, int irq, int type); 73 int mg_eisa_iomap(void *v, bus_addr_t addr, bus_size_t size, 74 int flags, bus_space_handle_t *bshp); 75 int mg_eisa_memmap(void *v, bus_addr_t addr, bus_size_t size, 76 int flags, bus_space_handle_t *bshp); 77 void mg_eisa_memunmap(void *v, bus_space_handle_t bsh, 78 bus_size_t size); 79 void mg_isa_barrier(void *v, bus_space_handle_t h, bus_size_t o, 80 bus_size_t l, int op); 81 u_int16_t mg_isa_r2(void *v, bus_space_handle_t h, bus_size_t o); 82 u_int32_t mg_isa_r4(void *v, bus_space_handle_t h, bus_size_t o); 83 void mg_isa_w2(void *v, bus_space_handle_t h, bus_size_t o, 84 u_int16_t vv); 85 void mg_isa_w4(void *v, bus_space_handle_t h, bus_size_t o, 86 u_int32_t vv); 87 void mg_isa_rm_2(void *v, bus_space_handle_t h, bus_size_t o, 88 u_int16_t *a, bus_size_t c); 89 void mg_isa_rm_4(void *v, bus_space_handle_t h, bus_size_t o, 90 u_int32_t *a, bus_size_t c); 91 void mg_isa_wm_2(void *v, bus_space_handle_t h, bus_size_t o, 92 const u_int16_t *a, bus_size_t c); 93 void mg_isa_wm_4(void *v, bus_space_handle_t h, bus_size_t o, 94 const u_int32_t *a, bus_size_t c); 95 void mg_isa_sm_2(void *v, bus_space_handle_t h, bus_size_t o, 96 u_int16_t vv, bus_size_t c); 97 void mg_isa_sm_4(void *v, bus_space_handle_t h, bus_size_t o, 98 u_int32_t vv, bus_size_t c); 99 void mg_isa_rr_2(void *v, bus_space_handle_t h, bus_size_t o, 100 u_int16_t *a, bus_size_t c); 101 void mg_isa_rr_4(void *v, bus_space_handle_t h, bus_size_t o, 102 u_int32_t *a, bus_size_t c); 103 void mg_isa_wr_2(void *v, bus_space_handle_t h, bus_size_t o, 104 const u_int16_t *a, bus_size_t c); 105 void mg_isa_wr_4(void *v, bus_space_handle_t h, bus_size_t o, 106 const u_int32_t *a, bus_size_t c); 107 void mg_isa_sr_2(void *v, bus_space_handle_t h, bus_size_t o, 108 u_int16_t vv, bus_size_t c); 109 void mg_isa_sr_4(void *v, bus_space_handle_t h, bus_size_t o, 110 u_int32_t vv, bus_size_t c); 111 112 /* TODO: DMA guts */ 113 114 void 115 mg_eisa_attach_hook(struct device *parent, struct device *self, 116 struct eisabus_attach_args *mg) 117 { 118 } 119 120 int 121 mg_intr_map(void *v, u_int irq, eisa_intr_handle_t *ehp) 122 { 123 *ehp = irq; 124 return 0; 125 } 126 127 const char * 128 mg_intr_string(void *v, int irq) 129 { 130 static char buf[16]; 131 132 snprintf(buf, sizeof buf, "isa irq %d", irq); 133 return buf; 134 } 135 136 void 137 mg_isa_attach_hook(struct device *parent, struct device *self, 138 struct isabus_attach_args *iba) 139 { 140 141 } 142 143 void * 144 mg_intr_establish(void *v, int irq, int type, int pri, 145 int (*handler)(void *), void *arg, const char *name) 146 { 147 struct hppa_isa_iv *iv; 148 struct mongoose_softc *sc = v; 149 volatile u_int8_t *imr, *pic; 150 151 if (!sc || irq < 0 || irq >= MONGOOSE_NINTS || 152 (0 <= irq && irq < MONGOOSE_NINTS && sc->sc_iv[irq].iv_handler)) 153 return NULL; 154 155 if (type != IST_LEVEL && type != IST_EDGE) { 156 #ifdef DEBUG 157 printf("%s: bad interrupt level (%d)\n", sc->sc_dev.dv_xname, 158 type); 159 #endif 160 return NULL; 161 } 162 163 iv = &sc->sc_iv[irq]; 164 if (iv->iv_handler) { 165 #ifdef DEBUG 166 printf("%s: irq %d already established\n", sc->sc_dev.dv_xname, 167 irq); 168 #endif 169 return NULL; 170 } 171 172 iv->iv_name = name; 173 iv->iv_pri = pri; 174 iv->iv_handler = handler; 175 iv->iv_arg = arg; 176 177 if (irq < 8) { 178 imr = &sc->sc_ctrl->imr0; 179 pic = &sc->sc_ctrl->pic0; 180 } else { 181 imr = &sc->sc_ctrl->imr1; 182 pic = &sc->sc_ctrl->pic1; 183 irq -= 8; 184 } 185 186 *imr |= 1 << irq; 187 *pic |= (type == IST_LEVEL) << irq; 188 189 /* TODO: ack it? */ 190 191 return iv; 192 } 193 194 void 195 mg_intr_disestablish(void *v, void *cookie) 196 { 197 struct hppa_isa_iv *iv = cookie; 198 struct mongoose_softc *sc = v; 199 int irq; 200 volatile u_int8_t *imr; 201 202 if (!sc || !cookie) 203 return; 204 205 irq = iv - sc->sc_iv; 206 if (irq < 8) 207 imr = &sc->sc_ctrl->imr0; 208 else 209 imr = &sc->sc_ctrl->imr1; 210 *imr &= ~(1 << irq); 211 /* TODO: ack it? */ 212 213 iv->iv_handler = NULL; 214 } 215 216 int 217 mg_intr_check(void *v, int irq, int type) 218 { 219 return 0; 220 } 221 222 int 223 mg_intr(void *v) 224 { 225 struct mongoose_softc *sc = v; 226 struct hppa_isa_iv *iv; 227 int s, irq = 0; 228 229 iv = &sc->sc_iv[irq]; 230 s = splraise(iv->iv_pri); 231 (iv->iv_handler)(iv->iv_arg); 232 splx(s); 233 234 return 0; 235 } 236 237 int 238 mg_eisa_iomap(void *v, bus_addr_t addr, bus_size_t size, int flags, 239 bus_space_handle_t *bshp) 240 { 241 struct mongoose_softc *sc = v; 242 243 /* see if it's ISA space we are mapping */ 244 if (0x100 <= addr && addr < 0x400) { 245 #define TOISA(a) ((((a) & 0x3f8) << 9) + ((a) & 7)) 246 size = TOISA(addr + size) - TOISA(addr); 247 addr = TOISA(addr); 248 } 249 250 return (sc->sc_bt->hbt_map)(NULL, sc->sc_iomap + addr, size, 251 flags, bshp); 252 } 253 254 int 255 mg_eisa_memmap(void *v, bus_addr_t addr, bus_size_t size, int flags, 256 bus_space_handle_t *bshp) 257 { 258 /* TODO: eisa memory map */ 259 return -1; 260 } 261 262 void 263 mg_eisa_memunmap(void *v, bus_space_handle_t bsh, bus_size_t size) 264 { 265 /* TODO: eisa memory unmap */ 266 } 267 268 void 269 mg_isa_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op) 270 { 271 sync_caches(); 272 } 273 274 u_int16_t 275 mg_isa_r2(void *v, bus_space_handle_t h, bus_size_t o) 276 { 277 register u_int16_t r = *((volatile u_int16_t *)(h + o)); 278 return letoh16(r); 279 } 280 281 u_int32_t 282 mg_isa_r4(void *v, bus_space_handle_t h, bus_size_t o) 283 { 284 register u_int32_t r = *((volatile u_int32_t *)(h + o)); 285 return letoh32(r); 286 } 287 288 void 289 mg_isa_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv) 290 { 291 *((volatile u_int16_t *)(h + o)) = htole16(vv); 292 } 293 294 void 295 mg_isa_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv) 296 { 297 *((volatile u_int32_t *)(h + o)) = htole32(vv); 298 } 299 300 void 301 mg_isa_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 302 { 303 h += o; 304 while (c--) 305 *(a++) = letoh16(*(volatile u_int16_t *)h); 306 } 307 308 void 309 mg_isa_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 310 { 311 h += o; 312 while (c--) 313 *(a++) = letoh32(*(volatile u_int32_t *)h); 314 } 315 316 void 317 mg_isa_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 318 { 319 register u_int16_t r; 320 h += o; 321 while (c--) { 322 r = *(a++); 323 *(volatile u_int16_t *)h = htole16(r); 324 } 325 } 326 327 void 328 mg_isa_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 329 { 330 register u_int32_t r; 331 h += o; 332 while (c--) { 333 r = *(a++); 334 *(volatile u_int32_t *)h = htole32(r); 335 } 336 } 337 338 void 339 mg_isa_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 340 { 341 vv = htole16(vv); 342 h += o; 343 while (c--) 344 *(volatile u_int16_t *)h = vv; 345 } 346 347 void 348 mg_isa_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 349 { 350 vv = htole32(vv); 351 h += o; 352 while (c--) 353 *(volatile u_int32_t *)h = vv; 354 } 355 356 void 357 mg_isa_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 358 { 359 volatile u_int16_t *p = (u_int16_t *)(h + o); 360 u_int32_t r; 361 362 while (c--) { 363 r = *p++; 364 *a++ = letoh16(r); 365 } 366 } 367 368 void 369 mg_isa_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 370 { 371 volatile u_int32_t *p = (u_int32_t *)(h + o); 372 u_int32_t r; 373 374 while (c--) { 375 r = *p++; 376 *a++ = letoh32(r); 377 } 378 } 379 380 void 381 mg_isa_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 382 { 383 volatile u_int16_t *p = (u_int16_t *)(h + o); 384 u_int32_t r; 385 386 while (c--) { 387 r = *a++; 388 *p++ = htole16(r); 389 } 390 } 391 392 void 393 mg_isa_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 394 { 395 volatile u_int32_t *p = (u_int32_t *)(h + o); 396 u_int32_t r; 397 398 while (c--) { 399 r = *a++; 400 *p++ = htole32(r); 401 } 402 } 403 404 void 405 mg_isa_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 406 { 407 volatile u_int16_t *p = (u_int16_t *)(h + o); 408 409 vv = htole16(vv); 410 while (c--) 411 *p++ = vv; 412 } 413 414 void 415 mg_isa_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 416 { 417 volatile u_int32_t *p = (u_int32_t *)(h + o); 418 419 vv = htole32(vv); 420 while (c--) 421 *p++ = vv; 422 } 423 424 int 425 mgattach_common(sc) 426 struct mongoose_softc *sc; 427 { 428 struct hppa_bus_space_tag *bt; 429 union mongoose_attach_args ea; 430 char brid[EISA_IDSTRINGLEN]; 431 432 viper_eisa_en(); 433 434 /* BUS RESET */ 435 sc->sc_ctrl->nmi_ext = MONGOOSE_NMI_BUSRESET; 436 DELAY(1); 437 sc->sc_ctrl->nmi_ext = 0; 438 DELAY(100); 439 440 /* determine eisa board id */ 441 { 442 u_int8_t id[4], *p; 443 p = (u_int8_t *)(sc->sc_iomap + EISA_SLOTOFF_VID); 444 id[0] = *p++; 445 id[1] = *p++; 446 id[2] = *p++; 447 id[3] = *p++; 448 449 brid[0] = EISA_VENDID_0(id); 450 brid[1] = EISA_VENDID_1(id); 451 brid[2] = EISA_VENDID_2(id); 452 brid[3] = EISA_PRODID_0(id + 2); 453 brid[4] = EISA_PRODID_1(id + 2); 454 brid[5] = EISA_PRODID_2(id + 2); 455 brid[6] = EISA_PRODID_3(id + 2); 456 brid[7] = '\0'; 457 } 458 459 printf (": %s rev %d, %d MHz\n", brid, sc->sc_regs->version, 460 (sc->sc_regs->clock? 33 : 25)); 461 sc->sc_regs->liowait = 1; /* disable isa wait states */ 462 sc->sc_regs->lock = 1; /* bus unlock */ 463 464 /* attach EISA */ 465 sc->sc_ec.ec_v = sc; 466 sc->sc_ec.ec_attach_hook = mg_eisa_attach_hook; 467 sc->sc_ec.ec_intr_establish = mg_intr_establish; 468 sc->sc_ec.ec_intr_disestablish = mg_intr_disestablish; 469 sc->sc_ec.ec_intr_string = mg_intr_string; 470 sc->sc_ec.ec_intr_map = mg_intr_map; 471 /* inherit the bus tags for eisa from the mainbus */ 472 bt = &sc->sc_eiot; 473 bcopy(sc->sc_bt, bt, sizeof(*bt)); 474 bt->hbt_cookie = sc; 475 bt->hbt_map = mg_eisa_iomap; 476 #define R(n) bt->__CONCAT(hbt_,n) = &__CONCAT(mg_isa_,n) 477 /* R(barrier); */ 478 R(r2); R(r4); R(w2); R(w4); 479 R(rm_2);R(rm_4);R(wm_2);R(wm_4);R(sm_2);R(sm_4); 480 R(rr_2);R(rr_4);R(wr_2);R(wr_4);R(sr_2);R(sr_4); 481 482 bt = &sc->sc_ememt; 483 bcopy(sc->sc_bt, bt, sizeof(*bt)); 484 bt->hbt_cookie = sc; 485 bt->hbt_map = mg_eisa_memmap; 486 bt->hbt_unmap = mg_eisa_memunmap; 487 /* attachment guts */ 488 ea.mongoose_eisa.eba_busname = "eisa"; 489 ea.mongoose_eisa.eba_iot = &sc->sc_eiot; 490 ea.mongoose_eisa.eba_memt = &sc->sc_ememt; 491 ea.mongoose_eisa.eba_dmat = NULL /* &sc->sc_edmat */; 492 ea.mongoose_eisa.eba_ec = &sc->sc_ec; 493 config_found((struct device *)sc, &ea.mongoose_eisa, mgprint); 494 495 sc->sc_ic.ic_v = sc; 496 sc->sc_ic.ic_attach_hook = mg_isa_attach_hook; 497 sc->sc_ic.ic_intr_establish = mg_intr_establish; 498 sc->sc_ic.ic_intr_disestablish = mg_intr_disestablish; 499 sc->sc_ic.ic_intr_check = mg_intr_check; 500 /* inherit the bus tags for isa from the eisa */ 501 bt = &sc->sc_imemt; 502 bcopy(&sc->sc_ememt, bt, sizeof(*bt)); 503 bt = &sc->sc_iiot; 504 bcopy(&sc->sc_eiot, bt, sizeof(*bt)); 505 /* TODO: DMA tags */ 506 /* attachment guts */ 507 ea.mongoose_isa.iba_busname = "isa"; 508 ea.mongoose_isa.iba_iot = &sc->sc_iiot; 509 ea.mongoose_isa.iba_memt = &sc->sc_imemt; 510 #if NISADMA > 0 511 ea.mongoose_isa.iba_dmat = &sc->sc_idmat; 512 #endif 513 ea.mongoose_isa.iba_ic = &sc->sc_ic; 514 config_found((struct device *)sc, &ea.mongoose_isa, mgprint); 515 #undef R 516 517 return (0); 518 } 519 520 int 521 mgprint(aux, pnp) 522 void *aux; 523 const char *pnp; 524 { 525 union mongoose_attach_args *ea = aux; 526 527 if (pnp) 528 printf ("%s at %s", ea->mongoose_name, pnp); 529 530 return (UNCONF); 531 } 532 533 int 534 mgmatch_gedoens(parent, cfdata, aux) 535 struct device *parent; 536 void *cfdata; 537 void *aux; 538 { 539 register struct confargs *ca = aux; 540 /* struct cfdata *cf = cfdata; */ 541 bus_space_handle_t ioh; 542 543 if (ca->ca_type.iodc_type != HPPA_TYPE_BHA || 544 (ca->ca_type.iodc_sv_model != HPPA_BHA_EISA && 545 ca->ca_type.iodc_sv_model != HPPA_BHA_WEISA)) 546 return 0; 547 548 if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE, 549 IOMOD_HPASIZE, 0, &ioh)) 550 return 0; 551 552 /* XXX check EISA signature */ 553 554 bus_space_unmap(ca->ca_iot, ioh, IOMOD_HPASIZE); 555 556 return 1; 557 } 558 559 void 560 mgattach_gedoens(parent, self, aux) 561 struct device *parent; 562 struct device *self; 563 void *aux; 564 { 565 register struct confargs *ca = aux; 566 register struct mongoose_softc *sc = (struct mongoose_softc *)self; 567 bus_space_handle_t ioh; 568 569 sc->sc_bt = ca->ca_iot; 570 sc->sc_iomap = ca->ca_hpa; 571 572 if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE, 573 sizeof(struct mongoose_regs), 0, &ioh) != 0) { 574 printf(": can't map IO space\n"); 575 return; 576 } 577 sc->sc_regs = (struct mongoose_regs *)ioh; 578 579 if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_CTRL, 580 sizeof(struct mongoose_ctrl), 0, &ioh) != 0) { 581 printf(": can't map control registers\n"); 582 bus_space_unmap(ca->ca_iot, (bus_space_handle_t)sc->sc_regs, 583 sizeof(struct mongoose_regs)); 584 return; 585 } 586 sc->sc_ctrl = (struct mongoose_ctrl *)ioh; 587 588 if (mgattach_common(sc) != 0) 589 return; 590 591 /* attach interrupt */ 592 sc->sc_ih = cpu_intr_establish(IPL_HIGH, ca->ca_irq, 593 mg_intr, sc, sc->sc_dev.dv_xname); 594 } 595