1 /* $OpenBSD: mongoose.c,v 1.21 2010/05/24 15:04:53 deraadt 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 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 = iv - sc->sc_iv; 200 volatile u_int8_t *imr; 201 202 if (!sc || !cookie) 203 return; 204 205 if (irq < 8) 206 imr = &sc->sc_ctrl->imr0; 207 else 208 imr = &sc->sc_ctrl->imr1; 209 *imr &= ~(1 << irq); 210 /* TODO: ack it? */ 211 212 iv->iv_handler = NULL; 213 } 214 215 int 216 mg_intr_check(void *v, int irq, int type) 217 { 218 return 0; 219 } 220 221 int 222 mg_intr(void *v) 223 { 224 struct mongoose_softc *sc = v; 225 struct hppa_isa_iv *iv; 226 int s, irq = 0; 227 228 iv = &sc->sc_iv[irq]; 229 s = splraise(iv->iv_pri); 230 (iv->iv_handler)(iv->iv_arg); 231 splx(s); 232 233 return 0; 234 } 235 236 int 237 mg_eisa_iomap(void *v, bus_addr_t addr, bus_size_t size, int flags, 238 bus_space_handle_t *bshp) 239 { 240 struct mongoose_softc *sc = v; 241 242 /* see if it's ISA space we are mapping */ 243 if (0x100 <= addr && addr < 0x400) { 244 #define TOISA(a) ((((a) & 0x3f8) << 9) + ((a) & 7)) 245 size = TOISA(addr + size) - TOISA(addr); 246 addr = TOISA(addr); 247 } 248 249 return (sc->sc_bt->hbt_map)(NULL, sc->sc_iomap + addr, size, 250 flags, bshp); 251 } 252 253 int 254 mg_eisa_memmap(void *v, bus_addr_t addr, bus_size_t size, int flags, 255 bus_space_handle_t *bshp) 256 { 257 /* TODO: eisa memory map */ 258 return -1; 259 } 260 261 void 262 mg_eisa_memunmap(void *v, bus_space_handle_t bsh, bus_size_t size) 263 { 264 /* TODO: eisa memory unmap */ 265 } 266 267 void 268 mg_isa_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op) 269 { 270 sync_caches(); 271 } 272 273 u_int16_t 274 mg_isa_r2(void *v, bus_space_handle_t h, bus_size_t o) 275 { 276 register u_int16_t r = *((volatile u_int16_t *)(h + o)); 277 return letoh16(r); 278 } 279 280 u_int32_t 281 mg_isa_r4(void *v, bus_space_handle_t h, bus_size_t o) 282 { 283 register u_int32_t r = *((volatile u_int32_t *)(h + o)); 284 return letoh32(r); 285 } 286 287 void 288 mg_isa_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv) 289 { 290 *((volatile u_int16_t *)(h + o)) = htole16(vv); 291 } 292 293 void 294 mg_isa_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv) 295 { 296 *((volatile u_int32_t *)(h + o)) = htole32(vv); 297 } 298 299 void 300 mg_isa_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 301 { 302 h += o; 303 while (c--) 304 *(a++) = letoh16(*(volatile u_int16_t *)h); 305 } 306 307 void 308 mg_isa_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 309 { 310 h += o; 311 while (c--) 312 *(a++) = letoh32(*(volatile u_int32_t *)h); 313 } 314 315 void 316 mg_isa_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 317 { 318 register u_int16_t r; 319 h += o; 320 while (c--) { 321 r = *(a++); 322 *(volatile u_int16_t *)h = htole16(r); 323 } 324 } 325 326 void 327 mg_isa_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 328 { 329 register u_int32_t r; 330 h += o; 331 while (c--) { 332 r = *(a++); 333 *(volatile u_int32_t *)h = htole32(r); 334 } 335 } 336 337 void 338 mg_isa_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 339 { 340 vv = htole16(vv); 341 h += o; 342 while (c--) 343 *(volatile u_int16_t *)h = vv; 344 } 345 346 void 347 mg_isa_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 348 { 349 vv = htole32(vv); 350 h += o; 351 while (c--) 352 *(volatile u_int32_t *)h = vv; 353 } 354 355 void 356 mg_isa_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 357 { 358 volatile u_int16_t *p = (u_int16_t *)(h + o); 359 u_int32_t r; 360 361 while (c--) { 362 r = *p++; 363 *a++ = letoh16(r); 364 } 365 } 366 367 void 368 mg_isa_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 369 { 370 volatile u_int32_t *p = (u_int32_t *)(h + o); 371 u_int32_t r; 372 373 while (c--) { 374 r = *p++; 375 *a++ = letoh32(r); 376 } 377 } 378 379 void 380 mg_isa_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 381 { 382 volatile u_int16_t *p = (u_int16_t *)(h + o); 383 u_int32_t r; 384 385 while (c--) { 386 r = *a++; 387 *p++ = htole16(r); 388 } 389 } 390 391 void 392 mg_isa_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 393 { 394 volatile u_int32_t *p = (u_int32_t *)(h + o); 395 u_int32_t r; 396 397 while (c--) { 398 r = *a++; 399 *p++ = htole32(r); 400 } 401 } 402 403 void 404 mg_isa_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 405 { 406 volatile u_int16_t *p = (u_int16_t *)(h + o); 407 408 vv = htole16(vv); 409 while (c--) 410 *p++ = vv; 411 } 412 413 void 414 mg_isa_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 415 { 416 volatile u_int32_t *p = (u_int32_t *)(h + o); 417 418 vv = htole32(vv); 419 while (c--) 420 *p++ = vv; 421 } 422 423 int 424 mgattach_common(sc) 425 struct mongoose_softc *sc; 426 { 427 struct hppa_bus_space_tag *bt; 428 union mongoose_attach_args ea; 429 char brid[EISA_IDSTRINGLEN]; 430 431 viper_eisa_en(); 432 433 /* BUS RESET */ 434 sc->sc_ctrl->nmi_ext = MONGOOSE_NMI_BUSRESET; 435 DELAY(1); 436 sc->sc_ctrl->nmi_ext = 0; 437 DELAY(100); 438 439 /* determine eisa board id */ 440 { 441 u_int8_t id[4], *p; 442 p = (u_int8_t *)(sc->sc_iomap + EISA_SLOTOFF_VID); 443 id[0] = *p++; 444 id[1] = *p++; 445 id[2] = *p++; 446 id[3] = *p++; 447 448 brid[0] = EISA_VENDID_0(id); 449 brid[1] = EISA_VENDID_1(id); 450 brid[2] = EISA_VENDID_2(id); 451 brid[3] = EISA_PRODID_0(id + 2); 452 brid[4] = EISA_PRODID_1(id + 2); 453 brid[5] = EISA_PRODID_2(id + 2); 454 brid[6] = EISA_PRODID_3(id + 2); 455 brid[7] = '\0'; 456 } 457 458 printf (": %s rev %d, %d MHz\n", brid, sc->sc_regs->version, 459 (sc->sc_regs->clock? 33 : 25)); 460 sc->sc_regs->liowait = 1; /* disable isa wait states */ 461 sc->sc_regs->lock = 1; /* bus unlock */ 462 463 /* attach EISA */ 464 sc->sc_ec.ec_v = sc; 465 sc->sc_ec.ec_attach_hook = mg_eisa_attach_hook; 466 sc->sc_ec.ec_intr_establish = mg_intr_establish; 467 sc->sc_ec.ec_intr_disestablish = mg_intr_disestablish; 468 sc->sc_ec.ec_intr_string = mg_intr_string; 469 sc->sc_ec.ec_intr_map = mg_intr_map; 470 /* inherit the bus tags for eisa from the mainbus */ 471 bt = &sc->sc_eiot; 472 bcopy(sc->sc_bt, bt, sizeof(*bt)); 473 bt->hbt_cookie = sc; 474 bt->hbt_map = mg_eisa_iomap; 475 #define R(n) bt->__CONCAT(hbt_,n) = &__CONCAT(mg_isa_,n) 476 /* R(barrier); */ 477 R(r2); R(r4); R(w2); R(w4); 478 R(rm_2);R(rm_4);R(wm_2);R(wm_4);R(sm_2);R(sm_4); 479 R(rr_2);R(rr_4);R(wr_2);R(wr_4);R(sr_2);R(sr_4); 480 481 bt = &sc->sc_ememt; 482 bcopy(sc->sc_bt, bt, sizeof(*bt)); 483 bt->hbt_cookie = sc; 484 bt->hbt_map = mg_eisa_memmap; 485 bt->hbt_unmap = mg_eisa_memunmap; 486 /* attachment guts */ 487 ea.mongoose_eisa.eba_busname = "eisa"; 488 ea.mongoose_eisa.eba_iot = &sc->sc_eiot; 489 ea.mongoose_eisa.eba_memt = &sc->sc_ememt; 490 ea.mongoose_eisa.eba_dmat = NULL /* &sc->sc_edmat */; 491 ea.mongoose_eisa.eba_ec = &sc->sc_ec; 492 config_found((struct device *)sc, &ea.mongoose_eisa, mgprint); 493 494 sc->sc_ic.ic_v = sc; 495 sc->sc_ic.ic_attach_hook = mg_isa_attach_hook; 496 sc->sc_ic.ic_intr_establish = mg_intr_establish; 497 sc->sc_ic.ic_intr_disestablish = mg_intr_disestablish; 498 sc->sc_ic.ic_intr_check = mg_intr_check; 499 /* inherit the bus tags for isa from the eisa */ 500 bt = &sc->sc_imemt; 501 bcopy(&sc->sc_ememt, bt, sizeof(*bt)); 502 bt = &sc->sc_iiot; 503 bcopy(&sc->sc_eiot, bt, sizeof(*bt)); 504 /* TODO: DMA tags */ 505 /* attachment guts */ 506 ea.mongoose_isa.iba_busname = "isa"; 507 ea.mongoose_isa.iba_iot = &sc->sc_iiot; 508 ea.mongoose_isa.iba_memt = &sc->sc_imemt; 509 #if NISADMA > 0 510 ea.mongoose_isa.iba_dmat = &sc->sc_idmat; 511 #endif 512 ea.mongoose_isa.iba_ic = &sc->sc_ic; 513 config_found((struct device *)sc, &ea.mongoose_isa, mgprint); 514 #undef R 515 516 return (0); 517 } 518 519 int 520 mgprint(aux, pnp) 521 void *aux; 522 const char *pnp; 523 { 524 union mongoose_attach_args *ea = aux; 525 526 if (pnp) 527 printf ("%s at %s", ea->mongoose_name, pnp); 528 529 return (UNCONF); 530 } 531 532 int 533 mgmatch_gedoens(parent, cfdata, aux) 534 struct device *parent; 535 void *cfdata; 536 void *aux; 537 { 538 register struct confargs *ca = aux; 539 /* struct cfdata *cf = cfdata; */ 540 bus_space_handle_t ioh; 541 542 if (ca->ca_type.iodc_type != HPPA_TYPE_BHA || 543 (ca->ca_type.iodc_sv_model != HPPA_BHA_EISA && 544 ca->ca_type.iodc_sv_model != HPPA_BHA_WEISA)) 545 return 0; 546 547 if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE, 548 IOMOD_HPASIZE, 0, &ioh)) 549 return 0; 550 551 /* XXX check EISA signature */ 552 553 bus_space_unmap(ca->ca_iot, ioh, IOMOD_HPASIZE); 554 555 return 1; 556 } 557 558 void 559 mgattach_gedoens(parent, self, aux) 560 struct device *parent; 561 struct device *self; 562 void *aux; 563 { 564 register struct confargs *ca = aux; 565 register struct mongoose_softc *sc = (struct mongoose_softc *)self; 566 bus_space_handle_t ioh; 567 568 sc->sc_bt = ca->ca_iot; 569 sc->sc_iomap = ca->ca_hpa; 570 571 if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE, 572 sizeof(struct mongoose_regs), 0, &ioh) != 0) { 573 printf(": can't map IO space\n"); 574 return; 575 } 576 sc->sc_regs = (struct mongoose_regs *)ioh; 577 578 if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_CTRL, 579 sizeof(struct mongoose_ctrl), 0, &ioh) != 0) { 580 printf(": can't map control registers\n"); 581 bus_space_unmap(ca->ca_iot, (bus_space_handle_t)sc->sc_regs, 582 sizeof(struct mongoose_regs)); 583 return; 584 } 585 sc->sc_ctrl = (struct mongoose_ctrl *)ioh; 586 587 if (mgattach_common(sc) != 0) 588 return; 589 590 /* attach interrupt */ 591 sc->sc_ih = cpu_intr_establish(IPL_HIGH, ca->ca_irq, 592 mg_intr, sc, sc->sc_dev.dv_xname); 593 } 594