1 /* $OpenBSD: mongoose.c,v 1.17 2004/11/08 20:54:04 miod 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 /* TODO: DMA guts */ 62 63 void 64 mg_eisa_attach_hook(struct device *parent, struct device *self, 65 struct eisabus_attach_args *mg) 66 { 67 } 68 69 int 70 mg_intr_map(void *v, u_int irq, eisa_intr_handle_t *ehp) 71 { 72 *ehp = irq; 73 return 0; 74 } 75 76 const char * 77 mg_intr_string(void *v, int irq) 78 { 79 static char buf[16]; 80 81 snprintf(buf, sizeof buf, "isa irq %d", irq); 82 return buf; 83 } 84 85 void 86 mg_isa_attach_hook(struct device *parent, struct device *self, 87 struct isabus_attach_args *iba) 88 { 89 90 } 91 92 void * 93 mg_intr_establish(void *v, int irq, int type, int pri, 94 int (*handler)(void *), void *arg, const char *name) 95 { 96 struct hppa_isa_iv *iv; 97 struct mongoose_softc *sc = v; 98 volatile u_int8_t *imr, *pic; 99 100 if (!sc || irq < 0 || irq >= MONGOOSE_NINTS || 101 (0 <= irq && irq < MONGOOSE_NINTS && sc->sc_iv[irq].iv_handler)) 102 return NULL; 103 104 if (type != IST_LEVEL && type != IST_EDGE) { 105 #ifdef DEBUG 106 printf("%s: bad interrupt level (%d)\n", sc->sc_dev.dv_xname, 107 type); 108 #endif 109 return NULL; 110 } 111 112 iv = &sc->sc_iv[irq]; 113 if (iv->iv_handler) { 114 #ifdef DEBUG 115 printf("%s: irq %d already established\n", sc->sc_dev.dv_xname, 116 irq); 117 #endif 118 return NULL; 119 } 120 121 iv->iv_name = name; 122 iv->iv_pri = pri; 123 iv->iv_handler = handler; 124 iv->iv_arg = arg; 125 126 if (irq < 8) { 127 imr = &sc->sc_ctrl->imr0; 128 pic = &sc->sc_ctrl->pic0; 129 } else { 130 imr = &sc->sc_ctrl->imr1; 131 pic = &sc->sc_ctrl->pic1; 132 irq -= 8; 133 } 134 135 *imr |= 1 << irq; 136 *pic |= (type == IST_LEVEL) << irq; 137 138 /* TODO: ack it? */ 139 140 return iv; 141 } 142 143 void 144 mg_intr_disestablish(void *v, void *cookie) 145 { 146 struct hppa_isa_iv *iv = cookie; 147 struct mongoose_softc *sc = v; 148 int irq = iv - sc->sc_iv; 149 volatile u_int8_t *imr; 150 151 if (!sc || !cookie) 152 return; 153 154 if (irq < 8) 155 imr = &sc->sc_ctrl->imr0; 156 else 157 imr = &sc->sc_ctrl->imr1; 158 *imr &= ~(1 << irq); 159 /* TODO: ack it? */ 160 161 iv->iv_handler = NULL; 162 } 163 164 int 165 mg_intr_check(void *v, int irq, int type) 166 { 167 return 0; 168 } 169 170 int 171 mg_intr(void *v) 172 { 173 struct mongoose_softc *sc = v; 174 struct hppa_isa_iv *iv; 175 int s, irq = 0; 176 177 iv = &sc->sc_iv[irq]; 178 s = splraise(iv->iv_pri); 179 (iv->iv_handler)(iv->iv_arg); 180 splx(s); 181 182 return 0; 183 } 184 185 int 186 mg_eisa_iomap(void *v, bus_addr_t addr, bus_size_t size, int cacheable, 187 bus_space_handle_t *bshp) 188 { 189 struct mongoose_softc *sc = v; 190 191 /* see if it's ISA space we are mapping */ 192 if (0x100 <= addr && addr < 0x400) { 193 #define TOISA(a) ((((a) & 0x3f8) << 9) + ((a) & 7)) 194 size = TOISA(addr + size) - TOISA(addr); 195 addr = TOISA(addr); 196 } 197 198 return (sc->sc_bt->hbt_map)(NULL, sc->sc_iomap + addr, size, 199 cacheable, bshp); 200 } 201 202 int 203 mg_eisa_memmap(void *v, bus_addr_t addr, bus_size_t size, int cacheable, 204 bus_space_handle_t *bshp) 205 { 206 /* TODO: eisa memory map */ 207 return -1; 208 } 209 210 void 211 mg_eisa_memunmap(void *v, bus_space_handle_t bsh, bus_size_t size) 212 { 213 /* TODO: eisa memory unmap */ 214 } 215 216 void 217 mg_isa_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op) 218 { 219 sync_caches(); 220 } 221 222 u_int16_t 223 mg_isa_r2(void *v, bus_space_handle_t h, bus_size_t o) 224 { 225 register u_int16_t r = *((volatile u_int16_t *)(h + o)); 226 return letoh16(r); 227 } 228 229 u_int32_t 230 mg_isa_r4(void *v, bus_space_handle_t h, bus_size_t o) 231 { 232 register u_int32_t r = *((volatile u_int32_t *)(h + o)); 233 return letoh32(r); 234 } 235 236 void 237 mg_isa_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv) 238 { 239 *((volatile u_int16_t *)(h + o)) = htole16(vv); 240 } 241 242 void 243 mg_isa_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv) 244 { 245 *((volatile u_int32_t *)(h + o)) = htole32(vv); 246 } 247 248 void 249 mg_isa_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 250 { 251 h += o; 252 while (c--) 253 *(a++) = letoh16(*(volatile u_int16_t *)h); 254 } 255 256 void 257 mg_isa_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 258 { 259 h += o; 260 while (c--) 261 *(a++) = letoh32(*(volatile u_int32_t *)h); 262 } 263 264 void 265 mg_isa_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 266 { 267 register u_int16_t r; 268 h += o; 269 while (c--) { 270 r = *(a++); 271 *(volatile u_int16_t *)h = htole16(r); 272 } 273 } 274 275 void 276 mg_isa_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 277 { 278 register u_int32_t r; 279 h += o; 280 while (c--) { 281 r = *(a++); 282 *(volatile u_int32_t *)h = htole32(r); 283 } 284 } 285 286 void 287 mg_isa_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 288 { 289 vv = htole16(vv); 290 h += o; 291 while (c--) 292 *(volatile u_int16_t *)h = vv; 293 } 294 295 void 296 mg_isa_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 297 { 298 vv = htole32(vv); 299 h += o; 300 while (c--) 301 *(volatile u_int32_t *)h = vv; 302 } 303 304 void 305 mg_isa_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) 306 { 307 register u_int16_t r; 308 h += o; 309 while (c--) { 310 r = *((volatile u_int16_t *)h)++; 311 *(a++) = letoh16(r); 312 } 313 } 314 315 void 316 mg_isa_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) 317 { 318 register u_int32_t r; 319 h += o; 320 while (c--) { 321 r = *((volatile u_int32_t *)h)++; 322 *(a++) = letoh32(r); 323 } 324 } 325 326 void 327 mg_isa_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) 328 { 329 register u_int16_t r; 330 h += o; 331 while (c--) { 332 r = *(a++); 333 *((volatile u_int16_t *)h)++ = htole16(r); 334 } 335 } 336 337 void 338 mg_isa_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) 339 { 340 register u_int32_t r; 341 h += o; 342 while (c--) { 343 r = *(a++); 344 *((volatile u_int32_t *)h)++ = htole32(r); 345 } 346 } 347 348 void 349 mg_isa_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) 350 { 351 vv = htole16(vv); 352 h += o; 353 while (c--) 354 *((volatile u_int16_t *)h)++ = vv; 355 } 356 357 void 358 mg_isa_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) 359 { 360 vv = htole32(vv); 361 h += o; 362 while (c--) 363 *((volatile u_int32_t *)h)++ = vv; 364 } 365 366 int 367 mgattach_common(sc) 368 struct mongoose_softc *sc; 369 { 370 struct hppa_bus_space_tag *bt; 371 union mongoose_attach_args ea; 372 char brid[EISA_IDSTRINGLEN]; 373 374 viper_eisa_en(); 375 376 /* BUS RESET */ 377 sc->sc_ctrl->nmi_ext = MONGOOSE_NMI_BUSRESET; 378 DELAY(1); 379 sc->sc_ctrl->nmi_ext = 0; 380 DELAY(100); 381 382 /* determine eisa board id */ 383 { 384 u_int8_t id[4], *p; 385 p = (u_int8_t *)(sc->sc_iomap + EISA_SLOTOFF_VID); 386 id[0] = *p++; 387 id[1] = *p++; 388 id[2] = *p++; 389 id[3] = *p++; 390 391 brid[0] = EISA_VENDID_0(id); 392 brid[1] = EISA_VENDID_1(id); 393 brid[2] = EISA_VENDID_2(id); 394 brid[3] = EISA_PRODID_0(id + 2); 395 brid[4] = EISA_PRODID_1(id + 2); 396 brid[5] = EISA_PRODID_2(id + 2); 397 brid[6] = EISA_PRODID_3(id + 2); 398 brid[7] = '\0'; 399 } 400 401 printf (": %s rev %d, %d MHz\n", brid, sc->sc_regs->version, 402 (sc->sc_regs->clock? 33 : 25)); 403 sc->sc_regs->liowait = 1; /* disable isa wait states */ 404 sc->sc_regs->lock = 1; /* bus unlock */ 405 406 /* attach EISA */ 407 sc->sc_ec.ec_v = sc; 408 sc->sc_ec.ec_attach_hook = mg_eisa_attach_hook; 409 sc->sc_ec.ec_intr_establish = mg_intr_establish; 410 sc->sc_ec.ec_intr_disestablish = mg_intr_disestablish; 411 sc->sc_ec.ec_intr_string = mg_intr_string; 412 sc->sc_ec.ec_intr_map = mg_intr_map; 413 /* inherit the bus tags for eisa from the mainbus */ 414 bt = &sc->sc_eiot; 415 bcopy(sc->sc_bt, bt, sizeof(*bt)); 416 bt->hbt_cookie = sc; 417 bt->hbt_map = mg_eisa_iomap; 418 #define R(n) bt->__CONCAT(hbt_,n) = &__CONCAT(mg_isa_,n) 419 /* R(barrier); */ 420 R(r2); R(r4); R(w2); R(w4); 421 R(rm_2);R(rm_4);R(wm_2);R(wm_4);R(sm_2);R(sm_4); 422 R(rr_2);R(rr_4);R(wr_2);R(wr_4);R(sr_2);R(sr_4); 423 424 bt = &sc->sc_ememt; 425 bcopy(sc->sc_bt, bt, sizeof(*bt)); 426 bt->hbt_cookie = sc; 427 bt->hbt_map = mg_eisa_memmap; 428 bt->hbt_unmap = mg_eisa_memunmap; 429 /* attachment guts */ 430 ea.mongoose_eisa.eba_busname = "eisa"; 431 ea.mongoose_eisa.eba_iot = &sc->sc_eiot; 432 ea.mongoose_eisa.eba_memt = &sc->sc_ememt; 433 ea.mongoose_eisa.eba_dmat = NULL /* &sc->sc_edmat */; 434 ea.mongoose_eisa.eba_ec = &sc->sc_ec; 435 config_found((struct device *)sc, &ea.mongoose_eisa, mgprint); 436 437 sc->sc_ic.ic_v = sc; 438 sc->sc_ic.ic_attach_hook = mg_isa_attach_hook; 439 sc->sc_ic.ic_intr_establish = mg_intr_establish; 440 sc->sc_ic.ic_intr_disestablish = mg_intr_disestablish; 441 sc->sc_ic.ic_intr_check = mg_intr_check; 442 /* inherit the bus tags for isa from the eisa */ 443 bt = &sc->sc_imemt; 444 bcopy(&sc->sc_ememt, bt, sizeof(*bt)); 445 bt = &sc->sc_iiot; 446 bcopy(&sc->sc_eiot, bt, sizeof(*bt)); 447 /* TODO: DMA tags */ 448 /* attachment guts */ 449 ea.mongoose_isa.iba_busname = "isa"; 450 ea.mongoose_isa.iba_iot = &sc->sc_iiot; 451 ea.mongoose_isa.iba_memt = &sc->sc_imemt; 452 #if NISADMA > 0 453 ea.mongoose_isa.iba_dmat = &sc->sc_idmat; 454 #endif 455 ea.mongoose_isa.iba_ic = &sc->sc_ic; 456 config_found((struct device *)sc, &ea.mongoose_isa, mgprint); 457 #undef R 458 459 return (0); 460 } 461 462 int 463 mgprint(aux, pnp) 464 void *aux; 465 const char *pnp; 466 { 467 union mongoose_attach_args *ea = aux; 468 469 if (pnp) 470 printf ("%s at %s", ea->mongoose_name, pnp); 471 472 return (UNCONF); 473 } 474 475 int 476 mgmatch_gedoens(parent, cfdata, aux) 477 struct device *parent; 478 void *cfdata; 479 void *aux; 480 { 481 register struct confargs *ca = aux; 482 /* struct cfdata *cf = cfdata; */ 483 bus_space_handle_t ioh; 484 485 if (ca->ca_type.iodc_type != HPPA_TYPE_BHA || 486 (ca->ca_type.iodc_sv_model != HPPA_BHA_EISA && 487 ca->ca_type.iodc_sv_model != HPPA_BHA_WEISA)) 488 return 0; 489 490 if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE, 491 IOMOD_HPASIZE, 0, &ioh)) 492 return 0; 493 494 /* XXX check EISA signature */ 495 496 bus_space_unmap(ca->ca_iot, ioh, IOMOD_HPASIZE); 497 498 return 1; 499 } 500 501 void 502 mgattach_gedoens(parent, self, aux) 503 struct device *parent; 504 struct device *self; 505 void *aux; 506 { 507 register struct confargs *ca = aux; 508 register struct mongoose_softc *sc = (struct mongoose_softc *)self; 509 510 sc->sc_bt = ca->ca_iot; 511 sc->sc_iomap = ca->ca_hpa; 512 sc->sc_regs = (struct mongoose_regs *)(ca->ca_hpa + MONGOOSE_MONGOOSE); 513 sc->sc_ctrl = (struct mongoose_ctrl *)(ca->ca_hpa + MONGOOSE_CTRL); 514 515 if (mgattach_common(sc) != 0) 516 return; 517 518 /* attach interrupt */ 519 sc->sc_ih = cpu_intr_establish(IPL_HIGH, ca->ca_irq, 520 mg_intr, sc, sc->sc_dev.dv_xname); 521 } 522