Annotation of sys/arch/hp300/dev/frodo.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: frodo.c,v 1.11 2007/01/14 17:54:45 miod Exp $ */
! 2: /* $NetBSD: frodo.c,v 1.5 1999/07/31 21:15:20 thorpej Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Jason R. Thorpe.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: /*
! 41: * Copyright (c) 1997 Michael Smith. All rights reserved.
! 42: *
! 43: * Redistribution and use in source and binary forms, with or without
! 44: * modification, are permitted provided that the following conditions
! 45: * are met:
! 46: * 1. Redistributions of source code must retain the above copyright
! 47: * notice, this list of conditions and the following disclaimer.
! 48: * 2. Redistributions in binary form must reproduce the above copyright
! 49: * notice, this list of conditions and the following disclaimer in the
! 50: * documentation and/or other materials provided with the distribution.
! 51: *
! 52: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 53: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 54: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 55: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 56: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 57: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 58: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 59: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 60: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 61: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 62: * SUCH DAMAGE.
! 63: */
! 64:
! 65: /*
! 66: * Support for the "Frodo" (a.k.a. "Apollo Utility") chip found
! 67: * in HP Apollo 9000/4xx workstations, as well as HP 9000/362 and 9000/382.
! 68: */
! 69:
! 70: #include <sys/param.h>
! 71: #include <sys/systm.h>
! 72: #include <sys/kernel.h>
! 73: #include <sys/syslog.h>
! 74: #include <sys/device.h>
! 75:
! 76: #include <machine/bus.h>
! 77: #include <machine/cpu.h>
! 78: #include <machine/intr.h>
! 79: #include <machine/hp300spu.h>
! 80:
! 81: #include <hp300/dev/intiovar.h>
! 82:
! 83: #include <hp300/dev/frodoreg.h>
! 84: #include <hp300/dev/frodovar.h>
! 85:
! 86: #include "isabr.h"
! 87:
! 88: #if NISABR > 0
! 89: #include <uvm/uvm_extern.h>
! 90:
! 91: #include <dev/isa/isareg.h>
! 92: #include <hp300/dev/isabrreg.h>
! 93: #endif
! 94:
! 95: struct frodo_softc {
! 96: struct device sc_dev; /* generic device glue */
! 97: volatile u_int8_t *sc_regs; /* register base */
! 98: struct isr *sc_intr[FRODO_NINTR]; /* interrupt handlers */
! 99: struct isr sc_isr; /* main interrupt handler */
! 100: u_int sc_refcnt; /* number of interrupt refs */
! 101: };
! 102:
! 103: int frodomatch(struct device *, void *, void *);
! 104: void frodoattach(struct device *, struct device *, void *);
! 105:
! 106: int frodoprint(void *, const char *);
! 107: int frodosubmatch(struct device *, void *, void *);
! 108:
! 109: int frodointr(void *);
! 110: void frodo_imask(struct frodo_softc *, u_int16_t, u_int16_t);
! 111: int frodo_isa_exists(void);
! 112: void frodo_state(struct frodo_softc *);
! 113:
! 114: struct cfattach frodo_ca = {
! 115: sizeof(struct frodo_softc), frodomatch, frodoattach
! 116: };
! 117:
! 118: struct cfdriver frodo_cd = {
! 119: NULL, "frodo", DV_DULL
! 120: };
! 121:
! 122: struct frodo_attach_args frodo_subdevs[] = {
! 123: { "dnkbd", NULL, FRODO_APCI_OFFSET(0), FRODO_INTR_APCI0 },
! 124: { "apci", NULL, FRODO_APCI_OFFSET(1), FRODO_INTR_APCI1 },
! 125: { "apci", NULL, FRODO_APCI_OFFSET(2), FRODO_INTR_APCI2 },
! 126: { "apci", NULL, FRODO_APCI_OFFSET(3), FRODO_INTR_APCI3 },
! 127: { NULL, NULL, 0, 0 },
! 128: };
! 129:
! 130: #define FRODO_IPL 5
! 131:
! 132: int
! 133: frodomatch(parent, match, aux)
! 134: struct device *parent;
! 135: void *match, *aux;
! 136: {
! 137: struct intio_attach_args *ia = aux;
! 138: caddr_t va;
! 139: static int frodo_matched = 0;
! 140:
! 141: /* only allow one instance */
! 142: if (frodo_matched)
! 143: return (0);
! 144:
! 145: /* only specific workstations can have this */
! 146: switch (machineid) {
! 147: case HP_362:
! 148: case HP_382:
! 149: case HP_400:
! 150: case HP_425:
! 151: case HP_433:
! 152: break;
! 153:
! 154: default:
! 155: return (0);
! 156: }
! 157:
! 158: /* make sure the hardware is there in any case */
! 159: va = (caddr_t)IIOV(FRODO_BASE);
! 160: if (badaddr(va))
! 161: return (0);
! 162:
! 163: frodo_matched = 1;
! 164: ia->ia_addr = (caddr_t)FRODO_BASE;
! 165: return (1);
! 166: }
! 167:
! 168: void
! 169: frodoattach(parent, self, aux)
! 170: struct device *parent, *self;
! 171: void *aux;
! 172: {
! 173: struct frodo_softc *sc = (struct frodo_softc *)self;
! 174: struct intio_attach_args *ia = aux;
! 175: int i;
! 176:
! 177: sc->sc_regs = (volatile u_int8_t *)IIOV(ia->ia_addr);
! 178:
! 179: printf(" ipl %d", FRODO_IPL);
! 180: if ((FRODO_READ(sc, FRODO_IISR) & FRODO_IISR_SERVICE) == 0)
! 181: printf(": service mode enabled");
! 182: printf("\n");
! 183:
! 184: /* Clear all of the interrupt handlers. */
! 185: bzero(sc->sc_intr, sizeof(sc->sc_intr));
! 186:
! 187: /*
! 188: * Disable all of the interrupt lines; we reenable them
! 189: * as subdevices attach.
! 190: */
! 191: frodo_imask(sc, 0, 0xffff);
! 192:
! 193: /* Clear any pending interrupts. */
! 194: FRODO_WRITE(sc, FRODO_PIC_PU, 0xff);
! 195: FRODO_WRITE(sc, FRODO_PIC_PL, 0xff);
! 196:
! 197: /* Set interrupt polarities... */
! 198: FRODO_WRITE(sc, FRODO_PIO_IPR, 0x10);
! 199:
! 200: /* ...and configure 1-5 for edge triggering. */
! 201: FRODO_WRITE(sc, FRODO_PIO_IELR, 0xc1);
! 202:
! 203: /* Initialize IVR high half to zero so we don't need to mask it later */
! 204: FRODO_WRITE(sc, FRODO_PIC_IVR, 0x00);
! 205:
! 206: /* Mask ISA interrupts until an ISA interrupt handler is registered. */
! 207: FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x80);
! 208:
! 209: /*
! 210: * We defer hooking up our interrupt handler until
! 211: * a subdevice hooks up theirs.
! 212: */
! 213: sc->sc_refcnt = 0;
! 214:
! 215: /* ... and attach subdevices. */
! 216: for (i = 0; frodo_subdevs[i].fa_name != NULL; i++) {
! 217: /*
! 218: * Skip the first serial port if we're not a 425e;
! 219: * it's mapped to the DCA at select code 9 on all
! 220: * other models.
! 221: */
! 222: if (frodo_subdevs[i].fa_offset == FRODO_APCI_OFFSET(1) &&
! 223: mmuid != MMUID_425_E)
! 224: continue;
! 225: frodo_subdevs[i].fa_tag = ia->ia_tag;
! 226: config_found_sm(self, &frodo_subdevs[i],
! 227: frodoprint, frodosubmatch);
! 228: }
! 229:
! 230: #if NISABR > 0
! 231: /*
! 232: * Only attempt to attach the isa bridge if it exists on this
! 233: * machine.
! 234: */
! 235: if (frodo_isa_exists()) {
! 236: struct frodo_attach_args fa;
! 237:
! 238: fa.fa_name = "isabr";
! 239: fa.fa_tag = ia->ia_tag;
! 240: fa.fa_offset = fa.fa_line = 0;
! 241: config_found_sm(self, &fa, frodoprint, frodosubmatch);
! 242: }
! 243: #endif
! 244: }
! 245:
! 246: int
! 247: frodosubmatch(parent, match, aux)
! 248: struct device *parent;
! 249: void *match, *aux;
! 250: {
! 251: struct cfdata *cf = match;
! 252: struct frodo_attach_args *fa = aux;
! 253:
! 254: if (cf->frodocf_offset != FRODO_UNKNOWN_OFFSET &&
! 255: cf->frodocf_offset != fa->fa_offset)
! 256: return (0);
! 257:
! 258: return ((*cf->cf_attach->ca_match)(parent, cf, aux));
! 259: }
! 260:
! 261: int
! 262: frodoprint(aux, pnp)
! 263: void *aux;
! 264: const char *pnp;
! 265: {
! 266: struct frodo_attach_args *fa = aux;
! 267:
! 268: if (pnp)
! 269: printf("%s at %s", fa->fa_name, pnp);
! 270: printf(" offset 0x%x", fa->fa_offset);
! 271: return (UNCONF);
! 272: }
! 273:
! 274: int
! 275: frodo_intr_establish(struct device *frdev, int line, struct isr *isr,
! 276: const char *name)
! 277: {
! 278: struct frodo_softc *sc = (struct frodo_softc *)frdev;
! 279: int priority = isr->isr_priority;
! 280:
! 281: if (line <= 0 || line >= FRODO_NINTR) {
! 282: panic("%s: bad interrupt line %d",
! 283: sc->sc_dev.dv_xname, line);
! 284: }
! 285: if (sc->sc_intr[line] != NULL) {
! 286: #ifdef DEBUG
! 287: printf("%s: interrupt line %d already used\n",
! 288: sc->sc_dev.dv_xname, line);
! 289: #endif
! 290: return (EPERM);
! 291: }
! 292:
! 293: /*
! 294: * If this is the first one, establish the frodo
! 295: * interrupt handler. If not, reestablish at a
! 296: * higher priority if necessary.
! 297: */
! 298: if (sc->sc_isr.isr_priority < priority) {
! 299: if (sc->sc_refcnt != 0)
! 300: intr_disestablish(&sc->sc_isr);
! 301: sc->sc_isr.isr_func = frodointr;
! 302: sc->sc_isr.isr_arg = sc;
! 303: sc->sc_isr.isr_ipl = FRODO_IPL;
! 304: sc->sc_isr.isr_priority = priority;
! 305: intr_establish(&sc->sc_isr, sc->sc_dev.dv_xname);
! 306: }
! 307:
! 308: sc->sc_refcnt++;
! 309:
! 310: /* Install the handler. */
! 311: isr->isr_ipl = sc->sc_isr.isr_ipl;
! 312: evcount_attach(&isr->isr_count, name, &isr->isr_ipl, &evcount_intr);
! 313: sc->sc_intr[line] = isr;
! 314:
! 315: /* Enable the interrupt line. */
! 316: frodo_imask(sc, FRODO_INTR_BIT(line), 0);
! 317:
! 318: #if NISABR > 0
! 319: /* Unmask ISA interrupts if necessary. */
! 320: if (FRODO_INTR_ISA(line))
! 321: FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x00);
! 322: #endif
! 323:
! 324: return (0);
! 325: }
! 326:
! 327: void
! 328: frodo_intr_disestablish(frdev, line)
! 329: struct device *frdev;
! 330: int line;
! 331: {
! 332: struct frodo_softc *sc = (struct frodo_softc *)frdev;
! 333: int newpri;
! 334:
! 335: #ifdef DIAGNOSTIC
! 336: if (sc->sc_intr[line] == NULL) {
! 337: printf("%s(%s): no handler for line %d",
! 338: sc->sc_dev.dv_xname, __func__, line);
! 339: return;
! 340: }
! 341: #endif
! 342:
! 343: sc->sc_intr[line] = NULL;
! 344: frodo_imask(sc, 0, FRODO_INTR_BIT(line));
! 345:
! 346: #if NISABR > 0
! 347: /* Mask ISA interrupts if necessary. */
! 348: if (FRODO_INTR_ISA(line)) {
! 349: if (sc->sc_intr[FRODO_INTR_ILOW] == NULL &&
! 350: sc->sc_intr[FRODO_INTR_IMID] == NULL &&
! 351: sc->sc_intr[FRODO_INTR_IHI] == NULL)
! 352: FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x80);
! 353: }
! 354: #endif
! 355:
! 356: /* If this was the last, unhook ourselves. */
! 357: if (sc->sc_refcnt-- == 1) {
! 358: intr_disestablish(&sc->sc_isr);
! 359: return;
! 360: }
! 361:
! 362: /* Lower our priority, if appropriate. */
! 363: for (newpri = 0, line = 0; line < FRODO_NINTR; line++)
! 364: if (sc->sc_intr[line] != NULL &&
! 365: sc->sc_intr[line]->isr_priority > newpri)
! 366: newpri = sc->sc_intr[line]->isr_priority;
! 367:
! 368: if (newpri != sc->sc_isr.isr_priority) {
! 369: intr_disestablish(&sc->sc_isr);
! 370: sc->sc_isr.isr_func = frodointr;
! 371: sc->sc_isr.isr_arg = sc;
! 372: sc->sc_isr.isr_ipl = FRODO_IPL;
! 373: sc->sc_isr.isr_priority = newpri;
! 374: intr_establish(&sc->sc_isr, sc->sc_dev.dv_xname);
! 375: }
! 376: }
! 377:
! 378: int
! 379: frodointr(arg)
! 380: void *arg;
! 381: {
! 382: struct frodo_softc *sc = arg;
! 383: struct isr *fisr;
! 384: int pending, line, rc = 0;
! 385:
! 386: #ifdef DEBUG
! 387: frodo_state(sc);
! 388: #endif
! 389:
! 390: /* Any interrupts pending? */
! 391: while ((pending = FRODO_GETPEND(sc)) != 0) {
! 392: rc++;
! 393:
! 394: /*
! 395: * Get pending interrupt; this also clears it for us.
! 396: */
! 397: line = FRODO_READ(sc, FRODO_PIC_ACK) /* & 0x0f */;
! 398:
! 399: fisr = sc->sc_intr[line];
! 400: if (fisr == NULL) {
! 401: printf("%s: unhandled interrupt on line %d\n",
! 402: sc->sc_dev.dv_xname, line);
! 403: #ifdef DEBUG
! 404: /* Disable interrupt source */
! 405: frodo_imask(sc, 0, FRODO_INTR_BIT(line));
! 406: #endif
! 407: } else {
! 408: if ((*fisr->isr_func)(fisr->isr_arg) != 0) {
! 409: fisr->isr_count.ec_count++;
! 410: } else {
! 411: printf("%s: spurious interrupt on line %d\n",
! 412: sc->sc_dev.dv_xname, line);
! 413: }
! 414: }
! 415:
! 416: if (rc > 100)
! 417: panic("frodointr: looping, pending %x line %d fisr %p",
! 418: pending, line, fisr);
! 419:
! 420: #ifdef DEBUG
! 421: frodo_state(sc);
! 422: #endif
! 423: }
! 424:
! 425: return (rc);
! 426: }
! 427:
! 428: void
! 429: frodo_imask(sc, set, clear)
! 430: struct frodo_softc *sc;
! 431: u_int16_t set, clear;
! 432: {
! 433: u_int16_t imask;
! 434:
! 435: imask = FRODO_GETMASK(sc);
! 436:
! 437: imask |= set;
! 438: imask &= ~clear;
! 439:
! 440: FRODO_SETMASK(sc, imask);
! 441: }
! 442:
! 443: #ifdef DEBUG
! 444: void
! 445: frodo_state(struct frodo_softc *sc)
! 446: {
! 447: int i;
! 448:
! 449: printf("%s state:", sc->sc_dev.dv_xname);
! 450: for (i = 0xc0; i < 0x100; i += 4) {
! 451: printf(" %02x", FRODO_READ(sc, i));
! 452: if (i == 0xcc || i == 0xdc || i == 0xec)
! 453: printf(" /");
! 454: }
! 455: printf("\n");
! 456: }
! 457: #endif
! 458:
! 459: #if NISABR > 0
! 460: int
! 461: frodo_isa_exists()
! 462: {
! 463: vaddr_t va;
! 464: int rv;
! 465:
! 466: va = uvm_km_valloc(kernel_map, PAGE_SIZE);
! 467: if (va == NULL)
! 468: return (0);
! 469:
! 470: /*
! 471: * Check that the iomem space answers probes
! 472: */
! 473: pmap_kenter_cache(va, ISABR_IOMEM_BASE, PG_RW | PG_CI);
! 474: pmap_update(pmap_kernel());
! 475: rv = badbaddr((caddr_t)va);
! 476: pmap_kremove(va, PAGE_SIZE);
! 477: pmap_update(pmap_kernel());
! 478:
! 479: /*
! 480: * Check that the ioport space answers probes
! 481: */
! 482: pmap_kenter_cache(va, ISABR_IOPORT_BASE, PG_RW | PG_CI);
! 483: pmap_update(pmap_kernel());
! 484: rv |= badbaddr((caddr_t)va);
! 485: pmap_kremove(va, PAGE_SIZE);
! 486: pmap_update(pmap_kernel());
! 487:
! 488: uvm_km_free(kernel_map, va, PAGE_SIZE);
! 489:
! 490: return (!rv);
! 491: }
! 492: #endif
CVSweb