1/* $NetBSD: algor_p5064_intr.c,v 1.30 2020/11/14 02:23:04 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Platform-specific interrupt support for the Algorithmics P-5064. 34 * 35 * The Algorithmics P-5064 has an interrupt controller that is pretty 36 * flexible -- it can take an interrupt source and route it to an 37 * arbitrary MIPS CPU hardware interrupt pin. 38 */ 39 40#include <sys/cdefs.h> 41__KERNEL_RCSID(0, "$NetBSD: algor_p5064_intr.c,v 1.30 2020/11/14 02:23:04 thorpej Exp $"); 42 43#include "opt_ddb.h" 44#define __INTR_PRIVATE 45 46#include <sys/param.h> 47#include <sys/bus.h> 48#include <sys/cpu.h> 49#include <sys/device.h> 50#include <sys/intr.h> 51#include <sys/kernel.h> 52#include <sys/kmem.h> 53#include <sys/queue.h> 54#include <sys/systm.h> 55 56#include <algor/autoconf.h> 57 58#include <mips/locore.h> 59 60#include <dev/ic/mc146818reg.h> 61 62#include <algor/algor/algor_p5064reg.h> 63#include <algor/algor/algor_p5064var.h> 64 65#include <dev/pci/pcireg.h> 66#include <dev/pci/pcivar.h> 67#include <dev/pci/pciidereg.h> 68#include <dev/pci/pciidevar.h> 69 70#include <dev/isa/isavar.h> 71 72#define REGVAL(x) *((volatile uint32_t *)(MIPS_PHYS_TO_KSEG1((x)))) 73 74struct p5064_irqreg { 75 bus_addr_t addr; 76 uint32_t val; 77}; 78 79#define IRQREG_LOCINT 0 80#define IRQREG_PANIC 1 81#define IRQREG_PCIINT 2 82#define IRQREG_ISAINT 3 83#define IRQREG_KBDINT 4 84#define NIRQREG 5 85 86struct p5064_irqreg p5064_irqregs[NIRQREG] = { 87 { P5064_LOCINT, 0 }, 88 { P5064_PANIC, 0 }, 89 { P5064_PCIINT, 0 }, 90 { P5064_ISAINT, 0 }, 91 { P5064_KBDINT, 0 }, 92}; 93 94#define NSTEERREG 5 95 96struct p5064_irqreg p5064_irqsteer[NSTEERREG] = { 97 { P5064_XBAR0, 0 }, 98 { P5064_XBAR1, 0 }, 99 { P5064_XBAR2, 0 }, 100 { P5064_XBAR3, 0 }, 101 { P5064_XBAR4, 0 }, 102}; 103 104#define NPCIIRQS 7 105 106#define NLOCIRQS 6 107 108#define NISAIRQS 3 109 110#define IRQMAP_PCIBASE 0 111#define IRQMAP_LOCBASE NPCIIRQS 112#define IRQMAP_ISABASE (IRQMAP_LOCBASE + NLOCIRQS) 113#define NIRQMAPS (IRQMAP_ISABASE + NISAIRQS) 114 115const char * const p5064_intrnames[NIRQMAPS] = { 116 /* 117 * PCI INTERRUPTS 118 */ 119 "PCIIRQ 0", 120 "PCIIRQ 1", 121 "PCIIRQ 2", 122 "PCIIRQ 3", 123 "Ethernet IRQ", 124 "SCSI IRQ", 125 "USB IRQ", 126 127 /* 128 * LOCAL INTERRUPTS 129 */ 130 "mkbd", 131 "com 1", 132 "com 2", 133 "floppy", 134 "centronics", 135 "mcclock", 136 137 /* 138 * ISA interrupts. 139 */ 140 "bridge", 141 "IDE primary", 142 "IDE secondary", 143}; 144 145struct p5064_irqmap { 146 int irqidx; 147 int cpuintr; 148 int irqreg; 149 int irqbit; 150 int xbarreg; 151 int xbarshift; 152}; 153 154const struct p5064_irqmap p5064_irqmap[NIRQMAPS] = { 155 /* 156 * PCI INTERRUPTS 157 */ 158 /* PCIIRQ 0 */ 159 { 0, 1, 160 IRQREG_PCIINT, PCIINT_PCI0, 161 2, 0 }, 162 163 /* PCIIRQ 1 */ 164 { 1, 1, 165 IRQREG_PCIINT, PCIINT_PCI1, 166 2, 2 }, 167 168 /* PCIIRQ 2 */ 169 { 2, 1, 170 IRQREG_PCIINT, PCIINT_PCI2, 171 2, 4 }, 172 173 /* PCIIRQ 3 */ 174 { 3, 1, 175 IRQREG_PCIINT, PCIINT_PCI3, 176 2, 6 }, 177 178 /* Ethernet */ 179 { P5064_IRQ_ETHERNET, 1, 180 IRQREG_PCIINT, PCIINT_ETH, 181 4, 2 }, 182 183 /* SCSI */ 184 { P5064_IRQ_SCSI, 1, 185 IRQREG_PCIINT, PCIINT_SCSI, 186 4, 4 }, 187 188 /* USB */ 189 { P5064_IRQ_USB, 1, 190 IRQREG_PCIINT, PCIINT_USB, 191 4, 6 }, 192 193 /* 194 * LOCAL INTERRUPTS 195 */ 196 /* keyboard */ 197 { P5064_IRQ_MKBD, 2, 198 IRQREG_LOCINT, LOCINT_MKBD, 199 0, 4 }, 200 201 /* COM1 */ 202 { P5064_IRQ_COM1, 2, 203 IRQREG_LOCINT, LOCINT_COM1, 204 0, 6 }, 205 206 /* COM2 */ 207 { P5064_IRQ_COM2, 2, 208 IRQREG_LOCINT, LOCINT_COM2, 209 1, 0 }, 210 211 /* floppy controller */ 212 { P5064_IRQ_FLOPPY, 2, 213 IRQREG_LOCINT, LOCINT_FLP, 214 0, 2 }, 215 216 /* parallel port */ 217 { P5064_IRQ_CENTRONICS, 2, 218 IRQREG_LOCINT, LOCINT_CENT, 219 1, 2 }, 220 221 /* RTC */ 222 { P5064_IRQ_RTC, 2, 223 IRQREG_LOCINT, LOCINT_RTC, 224 1, 6 }, 225 226 /* 227 * ISA INTERRUPTS 228 */ 229 /* ISA bridge */ 230 { P5064_IRQ_ISABRIDGE, 0, 231 IRQREG_ISAINT, ISAINT_ISABR, 232 3, 0 }, 233 234 /* IDE 0 */ 235 { P5064_IRQ_IDE0, 0, 236 IRQREG_ISAINT, ISAINT_IDE0, 237 3, 2 }, 238 239 /* IDE 1 */ 240 { P5064_IRQ_IDE1, 0, 241 IRQREG_ISAINT, ISAINT_IDE1, 242 3, 4 }, 243}; 244 245const int p5064_isa_to_irqmap[16] = { 246 -1, /* 0 */ 247 P5064_IRQ_MKBD, /* 1 */ 248 -1, /* 2 */ 249 P5064_IRQ_COM2, /* 3 */ 250 P5064_IRQ_COM1, /* 4 */ 251 -1, /* 5 */ 252 P5064_IRQ_FLOPPY, /* 6 */ 253 P5064_IRQ_CENTRONICS, /* 7 */ 254 P5064_IRQ_RTC, /* 8 */ 255 -1, /* 9 */ 256 -1, /* 10 */ 257 -1, /* 11 */ 258 P5064_IRQ_MKBD, /* 12 */ 259 -1, /* 13 */ 260 P5064_IRQ_IDE0, /* 14 */ 261 P5064_IRQ_IDE1, /* 15 */ 262}; 263 264struct p5064_intrhead { 265 struct evcnt intr_count; 266 int intr_refcnt; 267}; 268struct p5064_intrhead p5064_intrtab[NIRQMAPS]; 269 270#define NINTRS 3 /* MIPS INT0 - INT2 */ 271 272struct p5064_cpuintr { 273 LIST_HEAD(, evbmips_intrhand) cintr_list; 274 struct evcnt cintr_count; 275}; 276 277struct p5064_cpuintr p5064_cpuintrs[NINTRS]; 278const char * const p5064_cpuintrnames[NINTRS] = { 279 "int 0 (isa)", 280 "int 1 (pci)", 281 "int 2 (local)", 282}; 283 284const char * const p5064_intrgroups[NINTRS] = { 285 "isa", 286 "pci", 287 "local", 288}; 289 290void *algor_p5064_intr_establish(int, int (*)(void *), void *); 291void algor_p5064_intr_disestablish(void *); 292 293int algor_p5064_pci_intr_map(const struct pci_attach_args *, 294 pci_intr_handle_t *); 295const char *algor_p5064_pci_intr_string(void *, pci_intr_handle_t, char *, size_t); 296const struct evcnt *algor_p5064_pci_intr_evcnt(void *, pci_intr_handle_t); 297void *algor_p5064_pci_intr_establish(void *, pci_intr_handle_t, int, 298 int (*)(void *), void *); 299void algor_p5064_pci_intr_disestablish(void *, void *); 300void *algor_p5064_pciide_compat_intr_establish(void *, device_t, 301 const struct pci_attach_args *, int, int (*)(void *), void *); 302void algor_p5064_pci_conf_interrupt(void *, int, int, int, int, int *); 303 304const struct evcnt *algor_p5064_isa_intr_evcnt(void *, int); 305void *algor_p5064_isa_intr_establish(void *, int, int, int, 306 int (*)(void *), void *); 307void algor_p5064_isa_intr_disestablish(void *, void *); 308int algor_p5064_isa_intr_alloc(void *, int, int, int *); 309 310void algor_p5064_iointr(int, vaddr_t, uint32_t); 311 312void 313algor_p5064_intr_init(struct p5064_config *acp) 314{ 315 const struct p5064_irqmap *irqmap; 316 int i; 317 318 for (i = 0; i < NIRQREG; i++) 319 REGVAL(p5064_irqregs[i].addr) = p5064_irqregs[i].val; 320 321 for (i = 0; i < NINTRS; i++) { 322 LIST_INIT(&p5064_cpuintrs[i].cintr_list); 323 evcnt_attach_dynamic(&p5064_cpuintrs[i].cintr_count, 324 EVCNT_TYPE_INTR, NULL, "mips", p5064_cpuintrnames[i]); 325 } 326 327 for (i = 0; i < NIRQMAPS; i++) { 328 irqmap = &p5064_irqmap[i]; 329 330 p5064_irqsteer[irqmap->xbarreg].val |= 331 irqmap->cpuintr << irqmap->xbarshift; 332 333 evcnt_attach_dynamic(&p5064_intrtab[i].intr_count, 334 EVCNT_TYPE_INTR, NULL, p5064_intrgroups[irqmap->cpuintr], 335 p5064_intrnames[i]); 336 } 337 338 for (i = 0; i < NSTEERREG; i++) 339 REGVAL(p5064_irqsteer[i].addr) = p5064_irqsteer[i].val; 340 341 acp->ac_pc.pc_intr_v = NULL; 342 acp->ac_pc.pc_intr_map = algor_p5064_pci_intr_map; 343 acp->ac_pc.pc_intr_string = algor_p5064_pci_intr_string; 344 acp->ac_pc.pc_intr_evcnt = algor_p5064_pci_intr_evcnt; 345 acp->ac_pc.pc_intr_establish = algor_p5064_pci_intr_establish; 346 acp->ac_pc.pc_intr_disestablish = algor_p5064_pci_intr_disestablish; 347 acp->ac_pc.pc_conf_interrupt = algor_p5064_pci_conf_interrupt; 348 acp->ac_pc.pc_pciide_compat_intr_establish = 349 algor_p5064_pciide_compat_intr_establish; 350 351 acp->ac_ic.ic_v = NULL; 352 acp->ac_ic.ic_intr_evcnt = algor_p5064_isa_intr_evcnt; 353 acp->ac_ic.ic_intr_establish = algor_p5064_isa_intr_establish; 354 acp->ac_ic.ic_intr_disestablish = algor_p5064_isa_intr_disestablish; 355 acp->ac_ic.ic_intr_alloc = algor_p5064_isa_intr_alloc; 356 357 algor_intr_establish = algor_p5064_intr_establish; 358 algor_intr_disestablish = algor_p5064_intr_disestablish; 359 algor_iointr = algor_p5064_iointr; 360} 361 362void 363algor_p5064_cal_timer(bus_space_tag_t st, bus_space_handle_t sh) 364{ 365 u_long ctrdiff[4], startctr, endctr, cps; 366 uint32_t irr; 367 int i; 368 369 /* Disable interrupts first. */ 370 bus_space_write_1(st, sh, 0, MC_REGB); 371 bus_space_write_1(st, sh, 1, MC_REGB_SQWE | MC_REGB_BINARY | 372 MC_REGB_24HR); 373 374 /* Initialize for 16Hz. */ 375 bus_space_write_1(st, sh, 0, MC_REGA); 376 bus_space_write_1(st, sh, 1, MC_BASE_32_KHz | MC_RATE_16_Hz); 377 378 REGVAL(P5064_LOCINT) = LOCINT_RTC; 379 380 /* Run the loop an extra time to prime the cache. */ 381 for (i = 0; i < 4; i++) { 382 led_display('h', 'z', '0' + i, ' '); 383 384 /* Enable the interrupt. */ 385 bus_space_write_1(st, sh, 0, MC_REGB); 386 bus_space_write_1(st, sh, 1, MC_REGB_PIE | MC_REGB_SQWE | 387 MC_REGB_BINARY | MC_REGB_24HR); 388 389 /* Wait for it to happen. */ 390 startctr = mips3_cp0_count_read(); 391 do { 392 irr = REGVAL(P5064_LOCINT); 393 endctr = mips3_cp0_count_read(); 394 } while ((irr & LOCINT_RTC) == 0); 395 396 /* ACK. */ 397 bus_space_write_1(st, sh, 0, MC_REGC); 398 (void) bus_space_read_1(st, sh, 1); 399 400 /* Disable. */ 401 bus_space_write_1(st, sh, 0, MC_REGB); 402 bus_space_write_1(st, sh, 1, MC_REGB_SQWE | MC_REGB_BINARY | 403 MC_REGB_24HR); 404 405 ctrdiff[i] = endctr - startctr; 406 } 407 408 REGVAL(P5064_LOCINT) = 0; 409 410 /* Update CPU frequency values */ 411 cps = ((ctrdiff[2] + ctrdiff[3]) / 2) * 16; 412#if 1 413 /* XXX for unaccurate emulators */ 414 if (cps < 10 * 1000 * 1000) { 415 /* unlikely, use a reasonable value */ 416 cps = 75 * 1000 * 1000; 417 } 418#endif 419 /* XXX mips_cpu_flags isn't set here; assume CPU_MIPS_DOUBLE_COUNT */ 420 curcpu()->ci_cpu_freq = cps * 2; 421 curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz; 422 curcpu()->ci_divisor_delay = 423 ((curcpu()->ci_cpu_freq + (1000000 / 2)) / 1000000); 424 /* XXX assume CPU_MIPS_DOUBLE_COUNT */ 425 curcpu()->ci_cycles_per_hz /= 2; 426 curcpu()->ci_divisor_delay /= 2; 427 428 printf("Timer calibration: %lu cycles/sec [(%lu, %lu) * 16]\n", 429 cps, ctrdiff[2], ctrdiff[3]); 430 printf("CPU clock speed = %lu.%02luMHz " 431 "(hz cycles = %lu, delay divisor = %lu)\n", 432 curcpu()->ci_cpu_freq / 1000000, 433 (curcpu()->ci_cpu_freq % 1000000) / 10000, 434 curcpu()->ci_cycles_per_hz, curcpu()->ci_divisor_delay); 435} 436 437void * 438algor_p5064_intr_establish(int irq, int (*func)(void *), void *arg) 439{ 440 const struct p5064_irqmap *irqmap; 441 struct evbmips_intrhand *ih; 442 int s; 443 444 irqmap = &p5064_irqmap[irq]; 445 446 KASSERT(irq == irqmap->irqidx); 447 448 ih = kmem_alloc(sizeof(*ih), KM_SLEEP); 449 ih->ih_func = func; 450 ih->ih_arg = arg; 451 ih->ih_irq = 0; 452 ih->ih_irqmap = irqmap; 453 454 s = splhigh(); 455 456 /* 457 * First, link it into the tables. 458 */ 459 LIST_INSERT_HEAD(&p5064_cpuintrs[irqmap->cpuintr].cintr_list, 460 ih, ih_q); 461 462 /* 463 * Now enable it. 464 */ 465 if (p5064_intrtab[irqmap->irqidx].intr_refcnt++ == 0) { 466 p5064_irqregs[irqmap->irqreg].val |= irqmap->irqbit; 467 REGVAL(p5064_irqregs[irqmap->irqreg].addr) = 468 p5064_irqregs[irqmap->irqreg].val; 469 } 470 471 splx(s); 472 473 return (ih); 474} 475 476void 477algor_p5064_intr_disestablish(void *cookie) 478{ 479 const struct p5064_irqmap *irqmap; 480 struct evbmips_intrhand *ih = cookie; 481 int s; 482 483 irqmap = ih->ih_irqmap; 484 485 s = splhigh(); 486 487 /* 488 * First, remove it from the table. 489 */ 490 LIST_REMOVE(ih, ih_q); 491 492 /* 493 * Now, disable it, if there is nothing remaining on the 494 * list. 495 */ 496 if (p5064_intrtab[irqmap->irqidx].intr_refcnt-- == 1) { 497 p5064_irqregs[irqmap->irqreg].val &= ~irqmap->irqbit; 498 REGVAL(p5064_irqregs[irqmap->irqreg].addr) = 499 p5064_irqregs[irqmap->irqreg].val; 500 } 501 502 splx(s); 503 504 kmem_free(ih, sizeof(*ih)); 505} 506 507void 508algor_p5064_iointr(int ipl, vaddr_t pc, uint32_t ipending) 509{ 510 const struct p5064_irqmap *irqmap; 511 struct evbmips_intrhand *ih; 512 int level, i; 513 uint32_t irr[NIRQREG]; 514 515 /* Check for PANIC interrupts. */ 516 if (ipending & MIPS_INT_MASK_4) { 517 irr[IRQREG_PANIC] = REGVAL(p5064_irqregs[IRQREG_PANIC].addr); 518 if (irr[IRQREG_PANIC] & PANIC_IOPERR) 519 printf("WARNING: I/O parity error\n"); 520 if (irr[IRQREG_PANIC] & PANIC_ISANMI) 521 printf("WARNING: ISA NMI\n"); 522 if (irr[IRQREG_PANIC] & PANIC_BERR) 523 printf("WARNING: Bus error\n"); 524 if (irr[IRQREG_PANIC] & PANIC_PFAIL) 525 printf("WARNING: Power failure\n"); 526 if (irr[IRQREG_PANIC] & PANIC_DEBUG) { 527#ifdef DDB 528 printf("Debug switch -- entering debugger\n"); 529 led_display('D','D','B',' '); 530 Debugger(); 531 led_display('N','B','S','D'); 532#else 533 printf("Debug switch ignored -- " 534 "no debugger configured\n"); 535#endif 536 } 537 538 /* Clear them. */ 539 REGVAL(p5064_irqregs[IRQREG_PANIC].addr) = irr[IRQREG_PANIC]; 540 } 541 542 /* 543 * Read the interrupt pending registers, mask them with the 544 * ones we have enabled, and service them in order of decreasing 545 * priority. 546 */ 547 for (i = 0; i < NIRQREG; i++) { 548 if (i == IRQREG_PANIC) 549 continue; 550 irr[i] = REGVAL(p5064_irqregs[i].addr) & p5064_irqregs[i].val; 551 } 552 553 for (level = (NINTRS - 1); level >= 0; level--) { 554 if ((ipending & (MIPS_INT_MASK_0 << level)) == 0) 555 continue; 556 p5064_cpuintrs[level].cintr_count.ev_count++; 557 for (ih = LIST_FIRST(&p5064_cpuintrs[level].cintr_list); 558 ih != NULL; ih = LIST_NEXT(ih, ih_q)) { 559 irqmap = ih->ih_irqmap; 560 if (irr[irqmap->irqreg] & irqmap->irqbit) { 561 p5064_intrtab[ 562 irqmap->irqidx].intr_count.ev_count++; 563 (*ih->ih_func)(ih->ih_arg); 564 } 565 } 566 } 567} 568 569/***************************************************************************** 570 * PCI interrupt support 571 *****************************************************************************/ 572 573int 574algor_p5064_pci_intr_map(const struct pci_attach_args *pa, 575 pci_intr_handle_t *ihp) 576{ 577 static const int pciirqmap[6/*device*/][4/*pin*/] = { 578 { P5064_IRQ_ETHERNET, -1, -1, -1 }, /* 0: Ethernet */ 579 { P5064_IRQ_SCSI, -1, -1, -1 }, /* 1: SCSI */ 580 { -1, -1, -1, P5064_IRQ_USB }, /* 2: PCI-ISA bridge */ 581 { 0, 1, 2, 3 }, /* 3: PCI slot 3 */ 582 { 3, 0, 1, 2 }, /* 4: PCI slot 2 */ 583 { 2, 3, 0, 1 }, /* 5: PCI slot 1 */ 584 }; 585 pcitag_t bustag = pa->pa_intrtag; 586 int buspin = pa->pa_intrpin; 587 pci_chipset_tag_t pc = pa->pa_pc; 588 int device, irq; 589 590 if (buspin == 0) { 591 /* No IRQ used. */ 592 return (1); 593 } 594 595 if (buspin > 4) { 596 printf("algor_p5064_pci_intr_map: bad interrupt pin %d\n", 597 buspin); 598 return (1); 599 } 600 601 pci_decompose_tag(pc, bustag, NULL, &device, NULL); 602 if (device > 5) { 603 printf("algor_p5064_pci_intr_map: bad device %d\n", 604 device); 605 return (1); 606 } 607 608 irq = pciirqmap[device][buspin - 1]; 609 if (irq == -1) { 610 printf("algor_p5064_pci_intr_map: no mapping for " 611 "device %d pin %d\n", device, buspin); 612 return (1); 613 } 614 615 *ihp = irq; 616 return (0); 617} 618 619const char * 620algor_p5064_pci_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len) 621{ 622 623 if (ih >= NPCIIRQS) 624 panic("algor_p5064_intr_string: bogus IRQ %ld", ih); 625 626 strlcpy(buf, p5064_intrnames[ih], len); 627 return buf; 628} 629 630const struct evcnt * 631algor_p5064_pci_intr_evcnt(void *v, pci_intr_handle_t ih) 632{ 633 634 return (&p5064_intrtab[ih].intr_count); 635} 636 637void * 638algor_p5064_pci_intr_establish(void *v, pci_intr_handle_t ih, int level, 639 int (*func)(void *), void *arg) 640{ 641 642 if (ih >= NPCIIRQS) 643 panic("algor_p5064_intr_establish: bogus IRQ %ld", ih); 644 645 return (algor_p5064_intr_establish(ih, func, arg)); 646} 647 648void 649algor_p5064_pci_intr_disestablish(void *v, void *cookie) 650{ 651 652 return (algor_p5064_intr_disestablish(cookie)); 653} 654 655void 656algor_p5064_pci_conf_interrupt(void *v, int bus, int dev, int pin, int swiz, 657 int *iline) 658{ 659 660 /* 661 * We actually don't need to do anything; everything is handled 662 * in pci_intr_map(). 663 */ 664 *iline = 0; 665} 666 667void * 668algor_p5064_pciide_compat_intr_establish(void *v, device_t dev, 669 const struct pci_attach_args *pa, int chan, int (*func)(void *), void *arg) 670{ 671 pci_chipset_tag_t pc = pa->pa_pc; 672 void *cookie; 673 int bus; 674 675 pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL); 676 677 /* 678 * If this isn't PCI bus #0, all bets are off. 679 */ 680 if (bus != 0) 681 return (NULL); 682 683 cookie = algor_p5064_intr_establish(P5064_IRQ_IDE0 + chan, func, arg); 684 if (cookie == NULL) 685 return (NULL); 686 aprint_normal_dev(dev, "%s channel interrupting at on-board %s IRQ\n", 687 PCIIDE_CHANNEL_NAME(chan), p5064_intrnames[P5064_IRQ_IDE0 + chan]); 688 return (cookie); 689} 690 691/***************************************************************************** 692 * ISA interrupt support 693 *****************************************************************************/ 694 695const struct evcnt * 696algor_p5064_isa_intr_evcnt(void *v, int iirq) 697{ 698 699 /* XXX */ 700 return (NULL); 701} 702 703void * 704algor_p5064_isa_intr_establish(void *v, int iirq, int type, int level, 705 int (*func)(void *), void *arg) 706{ 707 struct evbmips_intrhand *ih; 708 int irqidx; 709 710 if (iirq > 15 || type == IST_NONE) 711 panic("algor_p5064_isa_intr_establish: bad irq or type"); 712 713 if ((irqidx = p5064_isa_to_irqmap[iirq]) == -1) 714 return (NULL); 715 716 ih = algor_p5064_intr_establish(irqidx, func, arg); 717 if (ih != NULL) { 718 /* Translate it to an ISA IRQ. */ 719 ih->ih_irq = iirq; 720 } 721 return (ih); 722} 723 724void 725algor_p5064_isa_intr_disestablish(void *v, void *cookie) 726{ 727 struct evbmips_intrhand *ih = cookie; 728 729 /* Translate the IRQ back to our domain. */ 730 ih->ih_irq = p5064_isa_to_irqmap[ih->ih_irq]; 731 732 algor_p5064_intr_disestablish(ih); 733} 734 735int 736algor_p5064_isa_intr_alloc(void *v, int mask, int type, int *iirq) 737{ 738 739 /* XXX */ 740 return (1); 741} 742