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