1 /* $NetBSD: pcib.c,v 1.15 2004/04/23 21:13:05 itojun Exp $ */ 2 3 /*- 4 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 40 41 __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.15 2004/04/23 21:13:05 itojun Exp $"); 42 43 #include "opt_algor_p5064.h" 44 #include "opt_algor_p6032.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/device.h> 50 #include <sys/malloc.h> 51 52 #include <machine/intr.h> 53 #include <machine/bus.h> 54 55 #include <dev/isa/isareg.h> 56 #include <dev/isa/isavar.h> 57 58 #include <dev/pci/pcireg.h> 59 #include <dev/pci/pcivar.h> 60 #include <dev/pci/pcidevs.h> 61 62 #include <dev/ic/i8259reg.h> 63 64 #ifdef ALGOR_P5064 65 #include <algor/algor/algor_p5064var.h> 66 #endif 67 68 #ifdef ALGOR_P6032 69 #include <algor/algor/algor_p6032var.h> 70 #endif 71 72 const char *pcib_intrnames[16] = { 73 "irq 0", 74 "irq 1", 75 "irq 2", 76 "irq 3", 77 "irq 4", 78 "irq 5", 79 "irq 6", 80 "irq 7", 81 "irq 8", 82 "irq 9", 83 "irq 10", 84 "irq 11", 85 "irq 12", 86 "irq 13", 87 "irq 14", 88 "irq 15", 89 }; 90 91 struct pcib_intrhead { 92 LIST_HEAD(, algor_intrhand) intr_q; 93 struct evcnt intr_count; 94 int intr_type; 95 }; 96 97 struct pcib_softc { 98 struct device sc_dev; 99 100 bus_space_tag_t sc_iot; 101 bus_space_handle_t sc_ioh_icu1; 102 bus_space_handle_t sc_ioh_icu2; 103 bus_space_handle_t sc_ioh_elcr; 104 105 struct algor_isa_chipset sc_ic; 106 107 struct pcib_intrhead sc_intrtab[16]; 108 109 u_int16_t sc_imask; 110 u_int16_t sc_elcr; 111 112 #if defined(ALGOR_P5064) 113 isa_chipset_tag_t sc_parent_ic; 114 #endif 115 116 u_int16_t sc_reserved; 117 118 void *sc_ih; 119 }; 120 121 int pcib_match(struct device *, struct cfdata *, void *); 122 void pcib_attach(struct device *, struct device *, void *); 123 124 CFATTACH_DECL(pcib, sizeof(struct pcib_softc), 125 pcib_match, pcib_attach, NULL, NULL); 126 127 int pcib_print(void *, const char *pnp); 128 void pcib_isa_attach_hook(struct device *, struct device *, 129 struct isabus_attach_args *); 130 131 int pcib_intr(void *); 132 133 void pcib_bridge_callback(struct device *); 134 135 const struct evcnt *pcib_isa_intr_evcnt(void *, int); 136 void *pcib_isa_intr_establish(void *, int, int, int, 137 int (*)(void *), void *); 138 void pcib_isa_intr_disestablish(void *, void *); 139 int pcib_isa_intr_alloc(void *, int, int, int *); 140 141 void pcib_set_icus(struct pcib_softc *); 142 143 int 144 pcib_match(struct device *parent, struct cfdata *match, void *aux) 145 { 146 struct pci_attach_args *pa = aux; 147 148 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 149 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) 150 return (1); 151 152 return (0); 153 } 154 155 void 156 pcib_attach(struct device *parent, struct device *self, void *aux) 157 { 158 struct pcib_softc *sc = (void *) self; 159 struct pci_attach_args *pa = aux; 160 char devinfo[256]; 161 int i; 162 163 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 164 printf(": %s (rev. 0x%02x)\n", devinfo, 165 PCI_REVISION(pa->pa_class)); 166 167 sc->sc_iot = pa->pa_iot; 168 169 /* 170 * Map the PIC/ELCR registers. 171 */ 172 if (bus_space_map(sc->sc_iot, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0) 173 printf("%s: unable to map ELCR registers\n", 174 sc->sc_dev.dv_xname); 175 if (bus_space_map(sc->sc_iot, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0) 176 printf("%s: unable to map ICU1 registers\n", 177 sc->sc_dev.dv_xname); 178 if (bus_space_map(sc->sc_iot, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0) 179 printf("%s: unable to map ICU2 registers\n", 180 sc->sc_dev.dv_xname); 181 182 /* All interrupts default to "masked off". */ 183 sc->sc_imask = 0xffff; 184 185 /* All interrupts default to edge-triggered. */ 186 sc->sc_elcr = 0; 187 188 /* 189 * Initialize the 8259s. 190 */ 191 192 /* reset, program device, 4 bytes */ 193 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW1, 194 ICW1_SELECT | ICW1_IC4); 195 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW2, 196 ICW2_VECTOR(0)/*XXX*/); 197 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW3, 198 ICW3_CASCADE(2)); 199 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW4, 200 ICW4_8086); 201 202 /* mask all interrupts */ 203 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1, 204 sc->sc_imask & 0xff); 205 206 /* enable special mask mode */ 207 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3, 208 OCW3_SELECT | OCW3_SSMM | OCW3_SMM); 209 210 /* read IRR by default */ 211 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3, 212 OCW3_SELECT | OCW3_RR); 213 214 /* reset; program device, 4 bytes */ 215 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW1, 216 ICW1_SELECT | ICW1_IC4); 217 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW2, 218 ICW2_VECTOR(0)/*XXX*/); 219 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW3, 220 ICW3_SIC(2)); 221 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW4, 222 ICW4_8086); 223 224 /* mask all interrupts */ 225 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1, 226 (sc->sc_imask >> 8) & 0xff); 227 228 /* enable special mask mode */ 229 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3, 230 OCW3_SELECT | OCW3_SSMM | OCW3_SMM); 231 232 /* read IRR by default */ 233 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3, 234 OCW3_SELECT | OCW3_RR); 235 236 /* 237 * Default all interrupts to edge-triggered. 238 */ 239 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0, 240 sc->sc_elcr & 0xff); 241 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1, 242 (sc->sc_elcr >> 8) & 0xff); 243 244 /* 245 * Some ISA interrupts are reserved for devices that 246 * we know are hard-wired to certain IRQs. 247 */ 248 sc->sc_reserved = 249 (1U << 0) | /* timer */ 250 (1U << 1) | /* keyboard controller */ 251 (1U << 2) | /* PIC cascade */ 252 (1U << 3) | /* COM 2 */ 253 (1U << 4) | /* COM 1 */ 254 (1U << 6) | /* floppy */ 255 (1U << 7) | /* centronics */ 256 (1U << 8) | /* RTC */ 257 (1U << 12) | /* keyboard controller */ 258 (1U << 14) | /* IDE 0 */ 259 (1U << 15); /* IDE 1 */ 260 261 #if defined(ALGOR_P5064) 262 /* 263 * Some "ISA" interrupts are a little wacky, wired up directly 264 * to the P-5064 interrupt controller. 265 */ 266 sc->sc_parent_ic = &p5064_configuration.ac_ic; 267 #endif /* ALGOR_P5064 */ 268 269 /* Set up our ISA chipset. */ 270 sc->sc_ic.ic_v = sc; 271 sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt; 272 sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish; 273 sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish; 274 sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc; 275 276 /* Initialize our interrupt table. */ 277 for (i = 0; i < 16; i++) { 278 LIST_INIT(&sc->sc_intrtab[i].intr_q); 279 evcnt_attach_dynamic(&sc->sc_intrtab[i].intr_count, 280 EVCNT_TYPE_INTR, NULL, "pcib", pcib_intrnames[i]); 281 sc->sc_intrtab[i].intr_type = IST_NONE; 282 } 283 284 /* Hook up our interrupt handler. */ 285 #if defined(ALGOR_P5064) 286 sc->sc_ih = (*algor_intr_establish)(P5064_IRQ_ISABRIDGE, 287 pcib_intr, sc); 288 #elif defined(ALGOR_P6032) 289 sc->sc_ih = (*algor_intr_establish)(P6032_IRQ_ISABRIDGE, 290 pcib_intr, sc); 291 #endif 292 if (sc->sc_ih == NULL) 293 printf("%s: WARNING: unable to register interrupt handler\n", 294 sc->sc_dev.dv_xname); 295 296 config_defer(self, pcib_bridge_callback); 297 } 298 299 void 300 pcib_bridge_callback(self) 301 struct device *self; 302 { 303 struct pcib_softc *sc = (struct pcib_softc *)self; 304 struct isabus_attach_args iba; 305 306 memset(&iba, 0, sizeof(iba)); 307 308 iba.iba_busname = "isa"; 309 #if defined(ALGOR_P5064) 310 { 311 struct p5064_config *acp = &p5064_configuration; 312 313 iba.iba_iot = &acp->ac_iot; 314 iba.iba_memt = &acp->ac_memt; 315 iba.iba_dmat = &acp->ac_isa_dmat; 316 } 317 #elif defined(ALGOR_P6032) 318 { 319 struct p6032_config *acp = &p6032_configuration; 320 321 iba.iba_iot = &acp->ac_iot; 322 iba.iba_memt = &acp->ac_memt; 323 iba.iba_dmat = &acp->ac_isa_dmat; 324 } 325 #endif 326 327 iba.iba_ic = &sc->sc_ic; 328 iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook; 329 330 (void) config_found(&sc->sc_dev, &iba, pcib_print); 331 } 332 333 int 334 pcib_print(void *aux, const char *pnp) 335 { 336 struct isabus_attach_args *iba = aux; 337 338 if (pnp) 339 aprint_normal("%s at %s", iba->iba_busname, pnp); 340 return (UNCONF); 341 } 342 343 void 344 pcib_isa_attach_hook(struct device *parent, struct device *self, 345 struct isabus_attach_args *iba) 346 { 347 348 /* Nothing to do. */ 349 } 350 351 void 352 pcib_set_icus(struct pcib_softc *sc) 353 { 354 355 /* Enable the cascade IRQ (2) if 8-15 is enabled. */ 356 if ((sc->sc_imask & 0xff00) != 0xff00) 357 sc->sc_imask &= ~(1U << 2); 358 else 359 sc->sc_imask |= (1U << 2); 360 361 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1, 362 sc->sc_imask & 0xff); 363 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1, 364 (sc->sc_imask >> 8) & 0xff); 365 366 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0, 367 sc->sc_elcr & 0xff); 368 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1, 369 (sc->sc_elcr >> 8) & 0xff); 370 } 371 372 int 373 pcib_intr(void *v) 374 { 375 struct pcib_softc *sc = v; 376 struct algor_intrhand *ih; 377 int irq; 378 379 for (;;) { 380 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3, 381 OCW3_SELECT | OCW3_POLL); 382 irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3); 383 if ((irq & OCW3_POLL_PENDING) == 0) 384 return (1); 385 386 irq = OCW3_POLL_IRQ(irq); 387 388 if (irq == 2) { 389 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 390 PIC_OCW3, OCW3_SELECT | OCW3_POLL); 391 irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2, 392 PIC_OCW3); 393 if (irq & OCW3_POLL_PENDING) 394 irq = OCW3_POLL_IRQ(irq) + 8; 395 else 396 irq = 2; 397 } 398 399 sc->sc_intrtab[irq].intr_count.ev_count++; 400 for (ih = LIST_FIRST(&sc->sc_intrtab[irq].intr_q); 401 ih != NULL; ih = LIST_NEXT(ih, ih_q)) { 402 (*ih->ih_func)(ih->ih_arg); 403 } 404 405 /* Send a specific EOI to the 8259. */ 406 if (irq > 7) { 407 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 408 PIC_OCW2, OCW2_SELECT | OCW3_EOI | OCW3_SL | 409 OCW2_ILS(irq & 7)); 410 irq = 2; 411 } 412 413 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW2, 414 OCW2_SELECT | OCW3_EOI | OCW3_SL | OCW2_ILS(irq)); 415 } 416 } 417 418 const struct evcnt * 419 pcib_isa_intr_evcnt(void *v, int irq) 420 { 421 struct pcib_softc *sc = v; 422 423 #if defined(ALGOR_P5064) 424 if (p5064_isa_to_irqmap[irq] != -1) 425 return (isa_intr_evcnt(sc->sc_parent_ic, irq)); 426 #endif 427 428 return (&sc->sc_intrtab[irq].intr_count); 429 } 430 431 void * 432 pcib_isa_intr_establish(void *v, int irq, int type, int level, 433 int (*func)(void *), void *arg) 434 { 435 struct pcib_softc *sc = v; 436 struct algor_intrhand *ih; 437 int s; 438 439 if (irq > 15 || irq == 2 || type == IST_NONE) 440 panic("pcib_isa_intr_establish: bad irq or type"); 441 442 #if defined(ALGOR_P5064) 443 if (p5064_isa_to_irqmap[irq] != -1) 444 return (isa_intr_establish(sc->sc_parent_ic, irq, type, 445 level, func, arg)); 446 #endif 447 448 switch (sc->sc_intrtab[irq].intr_type) { 449 case IST_NONE: 450 sc->sc_intrtab[irq].intr_type = type; 451 break; 452 453 case IST_EDGE: 454 case IST_LEVEL: 455 if (type == sc->sc_intrtab[irq].intr_type) 456 break; 457 /* FALLTHROUGH */ 458 case IST_PULSE: 459 /* 460 * We can't share interrupts in this case. 461 */ 462 return (NULL); 463 } 464 465 ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT); 466 if (ih == NULL) 467 return (NULL); 468 469 ih->ih_func = func; 470 ih->ih_arg = arg; 471 ih->ih_irq = irq; 472 ih->ih_irqmap = NULL; 473 474 s = splhigh(); 475 476 /* Insert the handler into the table. */ 477 LIST_INSERT_HEAD(&sc->sc_intrtab[irq].intr_q, ih, ih_q); 478 sc->sc_intrtab[irq].intr_type = type; 479 480 /* Enable it, set trigger mode. */ 481 sc->sc_imask &= ~(1 << irq); 482 if (sc->sc_intrtab[irq].intr_type == IST_LEVEL) 483 sc->sc_elcr |= (1 << irq); 484 else 485 sc->sc_elcr &= ~(1 << irq); 486 487 pcib_set_icus(sc); 488 489 splx(s); 490 491 return (ih); 492 } 493 494 void 495 pcib_isa_intr_disestablish(void *v, void *arg) 496 { 497 struct pcib_softc *sc = v; 498 struct algor_intrhand *ih = arg; 499 int s; 500 501 #if defined(ALGOR_P5064) 502 if (p5064_isa_to_irqmap[ih->ih_irq] != -1) { 503 isa_intr_disestablish(sc->sc_parent_ic, ih); 504 return; 505 } 506 #endif 507 508 s = splhigh(); 509 510 LIST_REMOVE(ih, ih_q); 511 512 /* If there are no more handlers on this IRQ, disable it. */ 513 if (LIST_FIRST(&sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) { 514 sc->sc_imask |= (1 << ih->ih_irq); 515 pcib_set_icus(sc); 516 } 517 518 splx(s); 519 520 free(ih, M_DEVBUF); 521 } 522 523 int 524 pcib_isa_intr_alloc(void *v, int mask, int type, int *irq) 525 { 526 struct pcib_softc *sc = v; 527 int i, tmp, bestirq, count; 528 struct algor_intrhand *ih; 529 530 if (type == IST_NONE) 531 panic("pcib_intr_alloc: bogus type"); 532 533 bestirq = -1; 534 count = -1; 535 536 mask &= ~sc->sc_reserved; 537 538 #if 0 539 printf("pcib_intr_alloc: mask = 0x%04x\n", mask); 540 #endif 541 542 for (i = 0; i < 16; i++) { 543 if ((mask & (1 << i)) == 0) 544 continue; 545 546 switch (sc->sc_intrtab[i].intr_type) { 547 case IST_NONE: 548 /* 549 * If nothing's using the IRQ, just return it. 550 */ 551 *irq = i; 552 return (0); 553 554 case IST_EDGE: 555 case IST_LEVEL: 556 if (type != sc->sc_intrtab[i].intr_type) 557 continue; 558 /* 559 * If the IRQ is sharable, count the number of 560 * other handlers, and if it's smaller than the 561 * last IRQ like this, remember it. 562 */ 563 tmp = 0; 564 for (ih = LIST_FIRST(&sc->sc_intrtab[i].intr_q); 565 ih != NULL; ih = LIST_NEXT(ih, ih_q)) 566 tmp++; 567 if (bestirq == -1 || count > tmp) { 568 bestirq = i; 569 count = tmp; 570 } 571 break; 572 573 case IST_PULSE: 574 /* This just isn't sharable. */ 575 continue; 576 } 577 } 578 579 if (bestirq == -1) 580 return (1); 581 582 *irq = bestirq; 583 return (0); 584 } 585