Annotation of sys/arch/alpha/pci/sio_pic.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sio_pic.c,v 1.26 2006/06/15 20:08:29 brad Exp $ */
! 2: /* $NetBSD: sio_pic.c,v 1.28 2000/06/06 03:10:13 thorpej Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1998, 2000 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 of the Numerical Aerospace Simulation Facility,
! 10: * NASA Ames Research Center.
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. All advertising materials mentioning features or use of this software
! 21: * must display the following acknowledgement:
! 22: * This product includes software developed by the NetBSD
! 23: * Foundation, Inc. and its contributors.
! 24: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 25: * contributors may be used to endorse or promote products derived
! 26: * from this software without specific prior written permission.
! 27: *
! 28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 38: * POSSIBILITY OF SUCH DAMAGE.
! 39: */
! 40:
! 41: /*
! 42: * Copyright (c) 1995, 1996 Carnegie-Mellon University.
! 43: * All rights reserved.
! 44: *
! 45: * Author: Chris G. Demetriou
! 46: *
! 47: * Permission to use, copy, modify and distribute this software and
! 48: * its documentation is hereby granted, provided that both the copyright
! 49: * notice and this permission notice appear in all copies of the
! 50: * software, derivative works or modified versions, and any portions
! 51: * thereof, and that both notices appear in supporting documentation.
! 52: *
! 53: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 54: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
! 55: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 56: *
! 57: * Carnegie Mellon requests users of this software to return to
! 58: *
! 59: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 60: * School of Computer Science
! 61: * Carnegie Mellon University
! 62: * Pittsburgh PA 15213-3890
! 63: *
! 64: * any improvements or extensions that they make and grant Carnegie the
! 65: * rights to redistribute these changes.
! 66: */
! 67:
! 68: #include <sys/param.h>
! 69: #include <sys/systm.h>
! 70:
! 71: #include <sys/device.h>
! 72: #include <sys/malloc.h>
! 73: #include <sys/syslog.h>
! 74:
! 75: #include <machine/intr.h>
! 76: #include <machine/bus.h>
! 77:
! 78: #include <dev/pci/pcireg.h>
! 79: #include <dev/pci/pcivar.h>
! 80: #include <dev/pci/pcidevs.h>
! 81:
! 82: #include <dev/pci/cy82c693reg.h>
! 83: #include <dev/pci/cy82c693var.h>
! 84:
! 85: #include <dev/isa/isareg.h>
! 86: #include <dev/isa/isavar.h>
! 87: #include <alpha/pci/siovar.h>
! 88:
! 89: #include "sio.h"
! 90:
! 91: /*
! 92: * To add to the long history of wonderful PROM console traits,
! 93: * AlphaStation PROMs don't reset themselves completely on boot!
! 94: * Therefore, if an interrupt was turned on when the kernel was
! 95: * started, we're not going to EVER turn it off... I don't know
! 96: * what will happen if new interrupts (that the PROM console doesn't
! 97: * want) are turned on. I'll burn that bridge when I come to it.
! 98: */
! 99: #define BROKEN_PROM_CONSOLE
! 100:
! 101: /*
! 102: * Private functions and variables.
! 103: */
! 104:
! 105: bus_space_tag_t sio_iot;
! 106: pci_chipset_tag_t sio_pc;
! 107: bus_space_handle_t sio_ioh_icu1, sio_ioh_icu2;
! 108:
! 109: #define ICU_LEN 16 /* number of ISA IRQs */
! 110:
! 111: static struct alpha_shared_intr *sio_intr;
! 112:
! 113: #ifndef STRAY_MAX
! 114: #define STRAY_MAX 5
! 115: #endif
! 116:
! 117: #ifdef BROKEN_PROM_CONSOLE
! 118: /*
! 119: * If prom console is broken, must remember the initial interrupt
! 120: * settings and enforce them. WHEE!
! 121: */
! 122: u_int8_t initial_ocw1[2];
! 123: u_int8_t initial_elcr[2];
! 124: #endif
! 125:
! 126: void sio_setirqstat(int, int, int);
! 127: int sio_intr_alloc(void *, int, int, int *);
! 128:
! 129: u_int8_t (*sio_read_elcr)(int);
! 130: void (*sio_write_elcr)(int, u_int8_t);
! 131: static void specific_eoi(int);
! 132: #ifdef BROKEN_PROM_CONSOLE
! 133: void sio_intr_shutdown(void *);
! 134: #endif
! 135:
! 136: /******************** i82378 SIO ELCR functions ********************/
! 137:
! 138: int i82378_setup_elcr(void);
! 139: u_int8_t i82378_read_elcr(int);
! 140: void i82378_write_elcr(int, u_int8_t);
! 141:
! 142: bus_space_handle_t sio_ioh_elcr;
! 143:
! 144: int
! 145: i82378_setup_elcr()
! 146: {
! 147: int rv;
! 148:
! 149: /*
! 150: * We could probe configuration space to see that there's
! 151: * actually an SIO present, but we are using this as a
! 152: * fall-back in case nothing else matches.
! 153: */
! 154:
! 155: rv = bus_space_map(sio_iot, 0x4d0, 2, 0, &sio_ioh_elcr);
! 156:
! 157: if (rv == 0) {
! 158: sio_read_elcr = i82378_read_elcr;
! 159: sio_write_elcr = i82378_write_elcr;
! 160: }
! 161:
! 162: return (rv);
! 163: }
! 164:
! 165: u_int8_t
! 166: i82378_read_elcr(elcr)
! 167: int elcr;
! 168: {
! 169:
! 170: return (bus_space_read_1(sio_iot, sio_ioh_elcr, elcr));
! 171: }
! 172:
! 173: void
! 174: i82378_write_elcr(elcr, val)
! 175: int elcr;
! 176: u_int8_t val;
! 177: {
! 178:
! 179: bus_space_write_1(sio_iot, sio_ioh_elcr, elcr, val);
! 180: }
! 181:
! 182: /******************** Cypress CY82C693 ELCR functions ********************/
! 183:
! 184: int cy82c693_setup_elcr(void);
! 185: u_int8_t cy82c693_read_elcr(int);
! 186: void cy82c693_write_elcr(int, u_int8_t);
! 187:
! 188: const struct cy82c693_handle *sio_cy82c693_handle;
! 189:
! 190: int
! 191: cy82c693_setup_elcr()
! 192: {
! 193: int device, maxndevs;
! 194: pcitag_t tag;
! 195: pcireg_t id;
! 196:
! 197: /*
! 198: * Search PCI configuration space for a Cypress CY82C693.
! 199: *
! 200: * Note we can make some assumptions about our bus number
! 201: * here, because:
! 202: *
! 203: * (1) there can be at most one ISA/EISA bridge per PCI bus, and
! 204: *
! 205: * (2) any ISA/EISA bridges must be attached to primary PCI
! 206: * busses (i.e. bus zero).
! 207: */
! 208:
! 209: maxndevs = pci_bus_maxdevs(sio_pc, 0);
! 210:
! 211: for (device = 0; device < maxndevs; device++) {
! 212: tag = pci_make_tag(sio_pc, 0, device, 0);
! 213: id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
! 214:
! 215: /* Invalid vendor ID value? */
! 216: if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
! 217: continue;
! 218: /* XXX Not invalid, but we've done this ~forever. */
! 219: if (PCI_VENDOR(id) == 0)
! 220: continue;
! 221:
! 222: if (PCI_VENDOR(id) != PCI_VENDOR_CONTAQ ||
! 223: PCI_PRODUCT(id) != PCI_PRODUCT_CONTAQ_82C693)
! 224: continue;
! 225:
! 226: /*
! 227: * Found one!
! 228: */
! 229:
! 230: #if 0
! 231: printf("cy82c693_setup_elcr: found 82C693 at device %d\n",
! 232: device);
! 233: #endif
! 234:
! 235: sio_cy82c693_handle = cy82c693_init(sio_iot);
! 236: sio_read_elcr = cy82c693_read_elcr;
! 237: sio_write_elcr = cy82c693_write_elcr;
! 238:
! 239: return (0);
! 240: }
! 241:
! 242: /*
! 243: * Didn't find a CY82C693.
! 244: */
! 245: return (ENODEV);
! 246: }
! 247:
! 248: u_int8_t
! 249: cy82c693_read_elcr(elcr)
! 250: int elcr;
! 251: {
! 252:
! 253: return (cy82c693_read(sio_cy82c693_handle, CONFIG_ELCR1 + elcr));
! 254: }
! 255:
! 256: void
! 257: cy82c693_write_elcr(elcr, val)
! 258: int elcr;
! 259: u_int8_t val;
! 260: {
! 261:
! 262: cy82c693_write(sio_cy82c693_handle, CONFIG_ELCR1 + elcr, val);
! 263: }
! 264:
! 265: /******************** ELCR access function configuration ********************/
! 266:
! 267: /*
! 268: * Put the Intel SIO at the end, so we fall back on it if we don't
! 269: * find anything else. If any of the non-Intel functions find a
! 270: * matching device, but are unable to map it for whatever reason,
! 271: * they should panic.
! 272: */
! 273:
! 274: int (*sio_elcr_setup_funcs[])(void) = {
! 275: cy82c693_setup_elcr,
! 276: i82378_setup_elcr,
! 277: NULL,
! 278: };
! 279:
! 280: /******************** Shared SIO/Cypress functions ********************/
! 281:
! 282: void
! 283: sio_setirqstat(irq, enabled, type)
! 284: int irq, enabled;
! 285: int type;
! 286: {
! 287: u_int8_t ocw1[2], elcr[2];
! 288: int icu, bit;
! 289:
! 290: #if 0
! 291: printf("sio_setirqstat: irq %d: %s, %s\n", irq,
! 292: enabled ? "enabled" : "disabled", isa_intr_typename(type));
! 293: #endif
! 294:
! 295: icu = irq / 8;
! 296: bit = irq % 8;
! 297:
! 298: ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
! 299: ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
! 300: elcr[0] = (*sio_read_elcr)(0); /* XXX */
! 301: elcr[1] = (*sio_read_elcr)(1); /* XXX */
! 302:
! 303: /*
! 304: * interrupt enable: set bit to mask (disable) interrupt.
! 305: */
! 306: if (enabled)
! 307: ocw1[icu] &= ~(1 << bit);
! 308: else
! 309: ocw1[icu] |= 1 << bit;
! 310:
! 311: /*
! 312: * interrupt type select: set bit to get level-triggered.
! 313: */
! 314: if (type == IST_LEVEL)
! 315: elcr[icu] |= 1 << bit;
! 316: else
! 317: elcr[icu] &= ~(1 << bit);
! 318:
! 319: #ifdef not_here
! 320: /* see the init function... */
! 321: ocw1[0] &= ~0x04; /* always enable IRQ2 on first PIC */
! 322: elcr[0] &= ~0x07; /* IRQ[0-2] must be edge-triggered */
! 323: elcr[1] &= ~0x21; /* IRQ[13,8] must be edge-triggered */
! 324: #endif
! 325:
! 326: bus_space_write_1(sio_iot, sio_ioh_icu1, 1, ocw1[0]);
! 327: bus_space_write_1(sio_iot, sio_ioh_icu2, 1, ocw1[1]);
! 328: (*sio_write_elcr)(0, elcr[0]); /* XXX */
! 329: (*sio_write_elcr)(1, elcr[1]); /* XXX */
! 330: }
! 331:
! 332: void
! 333: sio_intr_setup(pc, iot)
! 334: pci_chipset_tag_t pc;
! 335: bus_space_tag_t iot;
! 336: {
! 337: #ifdef notyet
! 338: char *cp;
! 339: #endif
! 340: int i;
! 341:
! 342: sio_iot = iot;
! 343: sio_pc = pc;
! 344:
! 345: if (bus_space_map(sio_iot, IO_ICU1, 2, 0, &sio_ioh_icu1) ||
! 346: bus_space_map(sio_iot, IO_ICU2, 2, 0, &sio_ioh_icu2))
! 347: panic("sio_intr_setup: can't map ICU I/O ports");
! 348:
! 349: for (i = 0; sio_elcr_setup_funcs[i] != NULL; i++)
! 350: if ((*sio_elcr_setup_funcs[i])() == 0)
! 351: break;
! 352: if (sio_elcr_setup_funcs[i] == NULL)
! 353: panic("sio_intr_setup: can't map ELCR");
! 354:
! 355: #ifdef BROKEN_PROM_CONSOLE
! 356: /*
! 357: * Remember the initial values, so we can restore them later.
! 358: */
! 359: initial_ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
! 360: initial_ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
! 361: initial_elcr[0] = (*sio_read_elcr)(0); /* XXX */
! 362: initial_elcr[1] = (*sio_read_elcr)(1); /* XXX */
! 363: shutdownhook_establish(sio_intr_shutdown, 0);
! 364: #endif
! 365:
! 366: sio_intr = alpha_shared_intr_alloc(ICU_LEN);
! 367:
! 368: /*
! 369: * set up initial values for interrupt enables.
! 370: */
! 371: for (i = 0; i < ICU_LEN; i++) {
! 372: alpha_shared_intr_set_maxstrays(sio_intr, i, STRAY_MAX);
! 373:
! 374: switch (i) {
! 375: case 0:
! 376: case 1:
! 377: case 8:
! 378: case 13:
! 379: /*
! 380: * IRQs 0, 1, 8, and 13 must always be
! 381: * edge-triggered.
! 382: */
! 383: sio_setirqstat(i, 0, IST_EDGE);
! 384: alpha_shared_intr_set_dfltsharetype(sio_intr, i,
! 385: IST_EDGE);
! 386: specific_eoi(i);
! 387: break;
! 388:
! 389: case 2:
! 390: /*
! 391: * IRQ 2 must be edge-triggered, and should be
! 392: * enabled (otherwise IRQs 8-15 are ignored).
! 393: */
! 394: sio_setirqstat(i, 1, IST_EDGE);
! 395: alpha_shared_intr_set_dfltsharetype(sio_intr, i,
! 396: IST_UNUSABLE);
! 397: break;
! 398:
! 399: default:
! 400: /*
! 401: * Otherwise, disable the IRQ and set its
! 402: * type to (effectively) "unknown."
! 403: */
! 404: sio_setirqstat(i, 0, IST_NONE);
! 405: alpha_shared_intr_set_dfltsharetype(sio_intr, i,
! 406: IST_NONE);
! 407: specific_eoi(i);
! 408: break;
! 409: }
! 410: }
! 411: }
! 412:
! 413: #ifdef BROKEN_PROM_CONSOLE
! 414: void
! 415: sio_intr_shutdown(arg)
! 416: void *arg;
! 417: {
! 418: /*
! 419: * Restore the initial values, to make the PROM happy.
! 420: */
! 421: bus_space_write_1(sio_iot, sio_ioh_icu1, 1, initial_ocw1[0]);
! 422: bus_space_write_1(sio_iot, sio_ioh_icu2, 1, initial_ocw1[1]);
! 423: (*sio_write_elcr)(0, initial_elcr[0]); /* XXX */
! 424: (*sio_write_elcr)(1, initial_elcr[1]); /* XXX */
! 425: }
! 426: #endif
! 427:
! 428: const char *
! 429: sio_intr_string(v, irq)
! 430: void *v;
! 431: int irq;
! 432: {
! 433: static char irqstr[12]; /* 8 + 2 + NULL + sanity */
! 434:
! 435: if (irq == 0 || irq >= ICU_LEN || irq == 2)
! 436: panic("sio_intr_string: bogus isa irq 0x%x", irq);
! 437:
! 438: snprintf(irqstr, sizeof irqstr, "isa irq %d", irq);
! 439: return (irqstr);
! 440: }
! 441:
! 442: int
! 443: sio_intr_line(v, irq)
! 444: void *v;
! 445: int irq;
! 446: {
! 447: return (irq);
! 448: }
! 449:
! 450: void *
! 451: sio_intr_establish(v, irq, type, level, fn, arg, name)
! 452: void *v, *arg;
! 453: int irq;
! 454: int type;
! 455: int level;
! 456: int (*fn)(void *);
! 457: char *name;
! 458: {
! 459: void *cookie;
! 460:
! 461: if (irq > ICU_LEN || type == IST_NONE)
! 462: panic("sio_intr_establish: bogus irq or type");
! 463:
! 464: cookie = alpha_shared_intr_establish(sio_intr, irq, type, level, fn,
! 465: arg, name);
! 466:
! 467: if (cookie != NULL &&
! 468: alpha_shared_intr_firstactive(sio_intr, irq)) {
! 469: scb_set(0x800 + SCB_IDXTOVEC(irq), sio_iointr, NULL);
! 470: sio_setirqstat(irq, 1,
! 471: alpha_shared_intr_get_sharetype(sio_intr, irq));
! 472: }
! 473:
! 474: return (cookie);
! 475: }
! 476:
! 477: void
! 478: sio_intr_disestablish(v, cookie)
! 479: void *v;
! 480: void *cookie;
! 481: {
! 482: struct alpha_shared_intrhand *ih = cookie;
! 483: int s, ist, irq = ih->ih_num;
! 484:
! 485: s = splhigh();
! 486:
! 487: /* Remove it from the link. */
! 488: alpha_shared_intr_disestablish(sio_intr, cookie, "isa irq");
! 489:
! 490: /*
! 491: * Decide if we should disable the interrupt. We must ensure
! 492: * that:
! 493: *
! 494: * - An initially-enabled interrupt is never disabled.
! 495: * - An initially-LT interrupt is never untyped.
! 496: */
! 497: if (alpha_shared_intr_isactive(sio_intr, irq) == 0) {
! 498: /*
! 499: * IRQs 0, 1, 8, and 13 must always be edge-triggered
! 500: * (see setup).
! 501: */
! 502: switch (irq) {
! 503: case 0:
! 504: case 1:
! 505: case 8:
! 506: case 13:
! 507: /*
! 508: * If the interrupt was initially level-triggered
! 509: * a warning was printed in setup.
! 510: */
! 511: ist = IST_EDGE;
! 512: break;
! 513:
! 514: default:
! 515: ist = IST_NONE;
! 516: break;
! 517: }
! 518: sio_setirqstat(irq, 0, ist);
! 519: alpha_shared_intr_set_dfltsharetype(sio_intr, irq, ist);
! 520:
! 521: /* Release our SCB vector. */
! 522: scb_free(0x800 + SCB_IDXTOVEC(irq));
! 523: }
! 524:
! 525: splx(s);
! 526: }
! 527:
! 528: void
! 529: sio_iointr(arg, vec)
! 530: void *arg;
! 531: unsigned long vec;
! 532: {
! 533: int irq;
! 534:
! 535: irq = SCB_VECTOIDX(vec - 0x800);
! 536:
! 537: #ifdef DIAGNOSTIC
! 538: if (irq >= ICU_LEN || irq < 0)
! 539: panic("sio_iointr: irq out of range (%d)", irq);
! 540: #endif
! 541:
! 542: if (!alpha_shared_intr_dispatch(sio_intr, irq))
! 543: alpha_shared_intr_stray(sio_intr, irq, "isa irq");
! 544: else
! 545: alpha_shared_intr_reset_strays(sio_intr, irq);
! 546:
! 547: /*
! 548: * Some versions of the machines which use the SIO
! 549: * (or is it some PALcode revisions on those machines?)
! 550: * require the non-specific EOI to be fed to the PIC(s)
! 551: * by the interrupt handler.
! 552: */
! 553: specific_eoi(irq);
! 554: }
! 555:
! 556: #define LEGAL_IRQ(x) ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
! 557:
! 558: int
! 559: sio_intr_alloc(v, mask, type, irq)
! 560: void *v;
! 561: int mask;
! 562: int type;
! 563: int *irq;
! 564: {
! 565: int i, tmp, bestirq, count;
! 566: struct alpha_shared_intrhand **p, *q;
! 567:
! 568: if (type == IST_NONE)
! 569: panic("intr_alloc: bogus type");
! 570:
! 571: bestirq = -1;
! 572: count = -1;
! 573:
! 574: /* some interrupts should never be dynamically allocated */
! 575: mask &= 0xdef8;
! 576:
! 577: /*
! 578: * XXX some interrupts will be used later (6 for fdc, 12 for pms).
! 579: * the right answer is to do "breadth-first" searching of devices.
! 580: */
! 581: mask &= 0xefbf;
! 582:
! 583: for (i = 0; i < ICU_LEN; i++) {
! 584: if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
! 585: continue;
! 586:
! 587: switch(sio_intr[i].intr_sharetype) {
! 588: case IST_NONE:
! 589: /*
! 590: * if nothing's using the irq, just return it
! 591: */
! 592: *irq = i;
! 593: return (0);
! 594:
! 595: case IST_EDGE:
! 596: case IST_LEVEL:
! 597: if (type != sio_intr[i].intr_sharetype)
! 598: continue;
! 599: /*
! 600: * if the irq is shareable, count the number of other
! 601: * handlers, and if it's smaller than the last irq like
! 602: * this, remember it
! 603: *
! 604: * XXX We should probably also consider the
! 605: * interrupt level and stick IPL_TTY with other
! 606: * IPL_TTY, etc.
! 607: */
! 608: for (p = &TAILQ_FIRST(&sio_intr[i].intr_q), tmp = 0;
! 609: (q = *p) != NULL; p = &TAILQ_NEXT(q, ih_q), tmp++)
! 610: ;
! 611: if ((bestirq == -1) || (count > tmp)) {
! 612: bestirq = i;
! 613: count = tmp;
! 614: }
! 615: break;
! 616:
! 617: case IST_PULSE:
! 618: /* this just isn't shareable */
! 619: continue;
! 620: }
! 621: }
! 622:
! 623: if (bestirq == -1)
! 624: return (1);
! 625:
! 626: *irq = bestirq;
! 627:
! 628: return (0);
! 629: }
! 630:
! 631: static void
! 632: specific_eoi(irq)
! 633: int irq;
! 634: {
! 635: if (irq > 7)
! 636: bus_space_write_1(sio_iot,
! 637: sio_ioh_icu2, 0, 0x20 | (irq & 0x07)); /* XXX */
! 638: bus_space_write_1(sio_iot, sio_ioh_icu1, 0, 0x20 | (irq > 7 ? 2 : irq));
! 639: }
CVSweb