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