1 1.33 thorpej /* $NetBSD: pci_6600.c,v 1.33 2021/07/04 22:42:36 thorpej Exp $ */ 2 1.1 ross 3 1.1 ross /*- 4 1.1 ross * Copyright (c) 1999 by Ross Harvey. All rights reserved. 5 1.1 ross * 6 1.1 ross * Redistribution and use in source and binary forms, with or without 7 1.1 ross * modification, are permitted provided that the following conditions 8 1.1 ross * are met: 9 1.1 ross * 1. Redistributions of source code must retain the above copyright 10 1.1 ross * notice, this list of conditions and the following disclaimer. 11 1.1 ross * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 ross * notice, this list of conditions and the following disclaimer in the 13 1.1 ross * documentation and/or other materials provided with the distribution. 14 1.1 ross * 3. All advertising materials mentioning features or use of this software 15 1.1 ross * must display the following acknowledgement: 16 1.1 ross * This product includes software developed by Ross Harvey. 17 1.1 ross * 4. The name of Ross Harvey may not be used to endorse or promote products 18 1.1 ross * derived from this software without specific prior written permission. 19 1.1 ross * 20 1.1 ross * THIS SOFTWARE IS PROVIDED BY ROSS HARVEY ``AS IS'' AND ANY EXPRESS 21 1.1 ross * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 1.1 ross * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP0SE 23 1.1 ross * ARE DISCLAIMED. IN NO EVENT SHALL ROSS HARVEY BE LIABLE FOR ANY 24 1.1 ross * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 1.1 ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 1.1 ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 1.1 ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.1 ross * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 1.1 ross * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 1.1 ross * SUCH DAMAGE. 31 1.1 ross * 32 1.1 ross */ 33 1.1 ross 34 1.1 ross #include <sys/cdefs.h> 35 1.1 ross 36 1.33 thorpej __KERNEL_RCSID(0, "$NetBSD: pci_6600.c,v 1.33 2021/07/04 22:42:36 thorpej Exp $"); 37 1.1 ross 38 1.1 ross #include <sys/param.h> 39 1.1 ross #include <sys/systm.h> 40 1.1 ross #include <sys/kernel.h> 41 1.1 ross #include <sys/device.h> 42 1.28 thorpej #include <sys/cpu.h> 43 1.6 mrg 44 1.1 ross #include <machine/autoconf.h> 45 1.1 ross #define _ALPHA_BUS_DMA_PRIVATE 46 1.23 dyoung #include <sys/bus.h> 47 1.1 ross #include <machine/rpb.h> 48 1.1 ross #include <machine/alpha.h> 49 1.1 ross 50 1.1 ross #include <dev/pci/pcireg.h> 51 1.1 ross #include <dev/pci/pcivar.h> 52 1.1 ross #include <dev/pci/pciidereg.h> 53 1.1 ross #include <dev/pci/pciidevar.h> 54 1.1 ross 55 1.1 ross #include <alpha/pci/tsreg.h> 56 1.1 ross #include <alpha/pci/tsvar.h> 57 1.1 ross 58 1.1 ross #define pci_6600() { Generate ctags(1) key. } 59 1.1 ross 60 1.1 ross #include "sio.h" 61 1.1 ross #if NSIO 62 1.1 ross #include <alpha/pci/siovar.h> 63 1.1 ross #endif 64 1.1 ross 65 1.4 thorpej #define PCI_NIRQ 64 66 1.27 thorpej #define PCI_SIO_IRQ 55 67 1.1 ross #define PCI_STRAY_MAX 5 68 1.1 ross 69 1.2 thorpej /* 70 1.2 thorpej * Some Tsunami models have a PCI device (the USB controller) with interrupts 71 1.2 thorpej * tied to ISA IRQ lines. The IRQ is encoded as: 72 1.2 thorpej * 73 1.2 thorpej * line = 0xe0 | isa_irq; 74 1.2 thorpej */ 75 1.2 thorpej #define DEC_6600_LINE_IS_ISA(line) ((line) >= 0xe0 && (line) <= 0xef) 76 1.2 thorpej #define DEC_6600_LINE_ISA_IRQ(line) ((line) & 0x0f) 77 1.2 thorpej 78 1.1 ross static struct tsp_config *sioprimary; 79 1.1 ross 80 1.26 thorpej static void dec_6600_intr_disestablish(pci_chipset_tag_t, void *); 81 1.26 thorpej static void *dec_6600_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, 82 1.26 thorpej int, int (*func)(void *), void *); 83 1.26 thorpej static const char *dec_6600_intr_string(pci_chipset_tag_t, pci_intr_handle_t, 84 1.26 thorpej char *, size_t); 85 1.26 thorpej static const struct evcnt *dec_6600_intr_evcnt(pci_chipset_tag_t, 86 1.26 thorpej pci_intr_handle_t); 87 1.26 thorpej static int dec_6600_intr_map(const struct pci_attach_args *, 88 1.26 thorpej pci_intr_handle_t *); 89 1.26 thorpej 90 1.26 thorpej static void *dec_6600_pciide_compat_intr_establish(device_t, 91 1.26 thorpej const struct pci_attach_args *, int, 92 1.26 thorpej int (*)(void *), void *); 93 1.26 thorpej 94 1.26 thorpej static void dec_6600_intr_enable(pci_chipset_tag_t, int irq); 95 1.26 thorpej static void dec_6600_intr_disable(pci_chipset_tag_t, int irq); 96 1.28 thorpej static void dec_6600_intr_set_affinity(pci_chipset_tag_t, int, 97 1.28 thorpej struct cpu_info *); 98 1.32 thorpej static void dec_6600_intr_program(pci_chipset_tag_t); 99 1.1 ross 100 1.29 thorpej static void dec_6600_intr_redistribute(void); 101 1.29 thorpej 102 1.28 thorpej /* 103 1.28 thorpej * We keep 2 software copies of the interrupt enables: one global one, 104 1.28 thorpej * and one per-CPU for setting the interrupt affinity. 105 1.28 thorpej */ 106 1.27 thorpej static uint64_t dec_6600_intr_enables __read_mostly; 107 1.28 thorpej static uint64_t dec_6600_cpu_intr_enables[4] __read_mostly; 108 1.27 thorpej 109 1.30 thorpej static void 110 1.30 thorpej pci_6600_pickintr(void *core, bus_space_tag_t iot, bus_space_tag_t memt, 111 1.30 thorpej pci_chipset_tag_t pc) 112 1.1 ross { 113 1.28 thorpej struct cpu_info *ci; 114 1.28 thorpej CPU_INFO_ITERATOR cii; 115 1.1 ross 116 1.30 thorpej pc->pc_intr_v = core; 117 1.24 matt pc->pc_intr_map = dec_6600_intr_map; 118 1.24 matt pc->pc_intr_string = dec_6600_intr_string; 119 1.3 cgd pc->pc_intr_evcnt = dec_6600_intr_evcnt; 120 1.24 matt pc->pc_intr_establish = dec_6600_intr_establish; 121 1.24 matt pc->pc_intr_disestablish = dec_6600_intr_disestablish; 122 1.26 thorpej 123 1.1 ross pc->pc_pciide_compat_intr_establish = NULL; 124 1.1 ross 125 1.31 thorpej pc->pc_intr_desc = "dec 6600"; 126 1.26 thorpej pc->pc_vecbase = 0x900; 127 1.26 thorpej pc->pc_nirq = PCI_NIRQ; 128 1.26 thorpej 129 1.26 thorpej pc->pc_intr_enable = dec_6600_intr_enable; 130 1.26 thorpej pc->pc_intr_disable = dec_6600_intr_disable; 131 1.28 thorpej pc->pc_intr_set_affinity = dec_6600_intr_set_affinity; 132 1.28 thorpej 133 1.29 thorpej alpha_intr_redistribute = dec_6600_intr_redistribute; 134 1.29 thorpej 135 1.28 thorpej /* Note eligible CPUs for interrupt routing purposes. */ 136 1.28 thorpej for (CPU_INFO_FOREACH(cii, ci)) { 137 1.28 thorpej KASSERT(ci->ci_cpuid < 4); 138 1.28 thorpej pc->pc_eligible_cpus |= __BIT(ci->ci_cpuid); 139 1.28 thorpej } 140 1.26 thorpej 141 1.1 ross /* 142 1.1 ross * System-wide and Pchip-0-only logic... 143 1.1 ross */ 144 1.26 thorpej if (sioprimary == NULL) { 145 1.30 thorpej sioprimary = core; 146 1.28 thorpej /* 147 1.28 thorpej * Unless explicitly routed, all interrupts go to the 148 1.28 thorpej * primary CPU. 149 1.28 thorpej */ 150 1.28 thorpej dec_6600_cpu_intr_enables[cpu_info_primary.ci_cpuid] = 151 1.28 thorpej __BITS(0,63); 152 1.1 ross pc->pc_pciide_compat_intr_establish = 153 1.1 ross dec_6600_pciide_compat_intr_establish; 154 1.32 thorpej 155 1.32 thorpej KASSERT(dec_6600_intr_enables == 0); 156 1.32 thorpej dec_6600_intr_program(pc); 157 1.32 thorpej 158 1.32 thorpej alpha_pci_intr_alloc(pc, PCI_STRAY_MAX); 159 1.1 ross #if NSIO 160 1.1 ross sio_intr_setup(pc, iot); 161 1.28 thorpej 162 1.28 thorpej mutex_enter(&cpu_lock); 163 1.28 thorpej dec_6600_intr_enable(pc, PCI_SIO_IRQ); 164 1.28 thorpej mutex_exit(&cpu_lock); 165 1.1 ross #endif 166 1.26 thorpej } else { 167 1.26 thorpej pc->pc_shared_intrs = sioprimary->pc_pc.pc_shared_intrs; 168 1.1 ross } 169 1.1 ross } 170 1.30 thorpej ALPHA_PCI_INTR_INIT(ST_DEC_6600, pci_6600_pickintr) 171 1.30 thorpej ALPHA_PCI_INTR_INIT(ST_DEC_TITAN, pci_6600_pickintr) 172 1.1 ross 173 1.26 thorpej static int 174 1.21 dyoung dec_6600_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 175 1.1 ross { 176 1.7 sommerfe pcitag_t bustag = pa->pa_intrtag; 177 1.7 sommerfe int buspin = pa->pa_intrpin, line = pa->pa_intrline; 178 1.7 sommerfe pci_chipset_tag_t pc = pa->pa_pc; 179 1.1 ross int bus, device, function; 180 1.1 ross 181 1.1 ross if (buspin == 0) { 182 1.1 ross /* No IRQ used. */ 183 1.1 ross return 1; 184 1.1 ross } 185 1.26 thorpej if (buspin < 0 || buspin > 4) { 186 1.1 ross printf("intr_map: bad interrupt pin %d\n", buspin); 187 1.1 ross return 1; 188 1.1 ross } 189 1.1 ross 190 1.9 thorpej pci_decompose_tag(pc, bustag, &bus, &device, &function); 191 1.2 thorpej 192 1.1 ross /* 193 1.1 ross * The console places the interrupt mapping in the "line" value. 194 1.1 ross * A value of (char)-1 indicates there is no mapping. 195 1.1 ross */ 196 1.2 thorpej if (line == 0xff) { 197 1.2 thorpej printf("dec_6600_intr_map: no mapping for %d/%d/%d\n", 198 1.2 thorpej bus, device, function); 199 1.1 ross return (1); 200 1.1 ross } 201 1.1 ross 202 1.2 thorpej #if NSIO == 0 203 1.2 thorpej if (DEC_6600_LINE_IS_ISA(line)) { 204 1.2 thorpej printf("dec_6600_intr_map: ISA IRQ %d for %d/%d/%d\n", 205 1.2 thorpej DEC_6600_LINE_ISA_IRQ(line), bus, device, function); 206 1.2 thorpej return (1); 207 1.2 thorpej } 208 1.2 thorpej #endif 209 1.2 thorpej 210 1.4 thorpej if (DEC_6600_LINE_IS_ISA(line) == 0 && line >= PCI_NIRQ) 211 1.10 provos panic("dec_6600_intr_map: dec 6600 irq too large (%d)", 212 1.2 thorpej line); 213 1.1 ross 214 1.26 thorpej alpha_pci_intr_handle_init(ihp, line, 0); 215 1.1 ross return (0); 216 1.1 ross } 217 1.1 ross 218 1.26 thorpej static const char * 219 1.26 thorpej dec_6600_intr_string(pci_chipset_tag_t const pc, pci_intr_handle_t const ih, 220 1.26 thorpej char * const buf, size_t const len) 221 1.1 ross { 222 1.26 thorpej #if NSIO 223 1.26 thorpej const u_int irq = alpha_pci_intr_handle_get_irq(&ih); 224 1.1 ross 225 1.26 thorpej if (DEC_6600_LINE_IS_ISA(irq)) 226 1.2 thorpej return (sio_intr_string(NULL /*XXX*/, 227 1.26 thorpej DEC_6600_LINE_ISA_IRQ(irq), buf, len)); 228 1.2 thorpej #endif 229 1.2 thorpej 230 1.26 thorpej return alpha_pci_generic_intr_string(pc, ih, buf, len); 231 1.3 cgd } 232 1.3 cgd 233 1.26 thorpej static const struct evcnt * 234 1.26 thorpej dec_6600_intr_evcnt(pci_chipset_tag_t const pc, pci_intr_handle_t const ih) 235 1.3 cgd { 236 1.26 thorpej #if NSIO 237 1.26 thorpej const u_int irq = alpha_pci_intr_handle_get_irq(&ih); 238 1.3 cgd 239 1.26 thorpej if (DEC_6600_LINE_IS_ISA(irq)) 240 1.3 cgd return (sio_intr_evcnt(NULL /*XXX*/, 241 1.26 thorpej DEC_6600_LINE_ISA_IRQ(irq))); 242 1.3 cgd #endif 243 1.3 cgd 244 1.26 thorpej return alpha_pci_generic_intr_evcnt(pc, ih); 245 1.1 ross } 246 1.1 ross 247 1.26 thorpej static void * 248 1.26 thorpej dec_6600_intr_establish(pci_chipset_tag_t const pc, pci_intr_handle_t const ih, 249 1.26 thorpej int const level, int (*func)(void *), void *arg) 250 1.1 ross { 251 1.26 thorpej #if NSIO 252 1.26 thorpej const u_int irq = alpha_pci_intr_handle_get_irq(&ih); 253 1.26 thorpej const u_int flags = alpha_pci_intr_handle_get_flags(&ih); 254 1.1 ross 255 1.26 thorpej if (DEC_6600_LINE_IS_ISA(irq)) 256 1.2 thorpej return (sio_intr_establish(NULL /*XXX*/, 257 1.26 thorpej DEC_6600_LINE_ISA_IRQ(irq), IST_LEVEL, level, flags, 258 1.26 thorpej func, arg)); 259 1.2 thorpej #endif 260 1.2 thorpej 261 1.26 thorpej return alpha_pci_generic_intr_establish(pc, ih, level, func, arg); 262 1.1 ross } 263 1.1 ross 264 1.26 thorpej static void 265 1.26 thorpej dec_6600_intr_disestablish(pci_chipset_tag_t const pc, void * const cookie) 266 1.1 ross { 267 1.26 thorpej #if NSIO 268 1.26 thorpej struct alpha_shared_intrhand * const ih = cookie; 269 1.2 thorpej 270 1.2 thorpej /* 271 1.2 thorpej * We have to determine if this is an ISA IRQ or not! We do this 272 1.2 thorpej * by checking to see if the intrhand points back to an intrhead 273 1.2 thorpej * that points to the sioprimary TSP. If not, it's an ISA IRQ. 274 1.2 thorpej * Pretty disgusting, eh? 275 1.2 thorpej */ 276 1.2 thorpej if (ih->ih_intrhead->intr_private != sioprimary) { 277 1.2 thorpej sio_intr_disestablish(NULL /*XXX*/, cookie); 278 1.2 thorpej return; 279 1.2 thorpej } 280 1.2 thorpej #endif 281 1.24 matt 282 1.26 thorpej return alpha_pci_generic_intr_disestablish(pc, cookie); 283 1.1 ross } 284 1.1 ross 285 1.26 thorpej static void 286 1.28 thorpej dec_6600_intr_program(pci_chipset_tag_t const pc) 287 1.1 ross { 288 1.28 thorpej unsigned int irq, cpuno, cnt; 289 1.28 thorpej 290 1.28 thorpej /* 291 1.28 thorpej * Validate the configuration before we program it: each enabled 292 1.28 thorpej * IRQ must be routed to exactly one CPU. 293 1.28 thorpej */ 294 1.28 thorpej for (irq = 0; irq < PCI_NIRQ; irq++) { 295 1.28 thorpej if ((dec_6600_intr_enables & __BIT(irq)) == 0) 296 1.28 thorpej continue; 297 1.28 thorpej for (cpuno = 0, cnt = 0; cpuno < 4; cpuno++) { 298 1.28 thorpej if (dec_6600_cpu_intr_enables[cpuno] != 0 && 299 1.28 thorpej (pc->pc_eligible_cpus & __BIT(cpuno)) == 0) 300 1.28 thorpej panic("%s: interrupts enabled on non-existent CPU %u", 301 1.28 thorpej __func__, cpuno); 302 1.28 thorpej if (dec_6600_cpu_intr_enables[cpuno] & __BIT(irq)) 303 1.28 thorpej cnt++; 304 1.28 thorpej } 305 1.28 thorpej if (cnt != 1) { 306 1.28 thorpej panic("%s: irq %u enabled on %u CPUs", __func__, 307 1.28 thorpej irq, cnt); 308 1.28 thorpej } 309 1.28 thorpej } 310 1.28 thorpej 311 1.28 thorpej const uint64_t enab0 = 312 1.28 thorpej dec_6600_intr_enables & dec_6600_cpu_intr_enables[0]; 313 1.28 thorpej const uint64_t enab1 = 314 1.28 thorpej dec_6600_intr_enables & dec_6600_cpu_intr_enables[1]; 315 1.28 thorpej const uint64_t enab2 = 316 1.28 thorpej dec_6600_intr_enables & dec_6600_cpu_intr_enables[2]; 317 1.28 thorpej const uint64_t enab3 = 318 1.28 thorpej dec_6600_intr_enables & dec_6600_cpu_intr_enables[3]; 319 1.28 thorpej 320 1.28 thorpej /* Don't touch DIMx registers for non-existent CPUs. */ 321 1.28 thorpej uint64_t black_hole; 322 1.28 thorpej volatile uint64_t * const dim0 = (pc->pc_eligible_cpus & __BIT(0)) ? 323 1.28 thorpej (void *)ALPHA_PHYS_TO_K0SEG(TS_C_DIM0) : &black_hole; 324 1.28 thorpej volatile uint64_t * const dim1 = (pc->pc_eligible_cpus & __BIT(1)) ? 325 1.28 thorpej (void *)ALPHA_PHYS_TO_K0SEG(TS_C_DIM1) : &black_hole; 326 1.28 thorpej volatile uint64_t * const dim2 = (pc->pc_eligible_cpus & __BIT(2)) ? 327 1.28 thorpej (void *)ALPHA_PHYS_TO_K0SEG(TS_C_DIM2) : &black_hole; 328 1.28 thorpej volatile uint64_t * const dim3 = (pc->pc_eligible_cpus & __BIT(3)) ? 329 1.28 thorpej (void *)ALPHA_PHYS_TO_K0SEG(TS_C_DIM3) : &black_hole; 330 1.28 thorpej 331 1.28 thorpej const unsigned long psl = alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); 332 1.28 thorpej 333 1.28 thorpej alpha_mb(); 334 1.28 thorpej *dim0 = enab0; 335 1.28 thorpej *dim1 = enab1; 336 1.28 thorpej *dim2 = enab2; 337 1.28 thorpej *dim3 = enab3; 338 1.1 ross alpha_mb(); 339 1.28 thorpej (void) *dim0; 340 1.28 thorpej (void) *dim1; 341 1.28 thorpej (void) *dim2; 342 1.28 thorpej (void) *dim3; 343 1.1 ross alpha_mb(); 344 1.28 thorpej 345 1.28 thorpej alpha_pal_swpipl(psl); 346 1.1 ross } 347 1.1 ross 348 1.26 thorpej static void 349 1.28 thorpej dec_6600_intr_enable(pci_chipset_tag_t const pc, int const irq) 350 1.1 ross { 351 1.28 thorpej 352 1.28 thorpej KASSERT(mutex_owned(&cpu_lock)); 353 1.28 thorpej 354 1.28 thorpej dec_6600_intr_enables |= __BIT(irq); 355 1.28 thorpej dec_6600_intr_program(pc); 356 1.28 thorpej } 357 1.28 thorpej 358 1.28 thorpej static void 359 1.28 thorpej dec_6600_intr_disable(pci_chipset_tag_t const pc, int const irq) 360 1.28 thorpej { 361 1.28 thorpej 362 1.28 thorpej KASSERT(mutex_owned(&cpu_lock)); 363 1.28 thorpej 364 1.28 thorpej dec_6600_intr_enables &= ~__BIT(irq); 365 1.28 thorpej dec_6600_intr_program(pc); 366 1.28 thorpej } 367 1.28 thorpej 368 1.28 thorpej static void 369 1.28 thorpej dec_6600_intr_set_affinity(pci_chipset_tag_t const pc, int const irq, 370 1.28 thorpej struct cpu_info * const ci) 371 1.28 thorpej { 372 1.28 thorpej const uint64_t intr_bit = __BIT(irq); 373 1.28 thorpej cpuid_t cpuno; 374 1.28 thorpej 375 1.28 thorpej KASSERT(mutex_owned(&cpu_lock)); 376 1.28 thorpej KASSERT(ci->ci_cpuid < 4); 377 1.28 thorpej KASSERT(pc->pc_eligible_cpus & __BIT(ci->ci_cpuid)); 378 1.28 thorpej 379 1.28 thorpej for (cpuno = 0; cpuno < 4; cpuno++) { 380 1.28 thorpej if (cpuno == ci->ci_cpuid) 381 1.28 thorpej dec_6600_cpu_intr_enables[cpuno] |= intr_bit; 382 1.28 thorpej else 383 1.28 thorpej dec_6600_cpu_intr_enables[cpuno] &= ~intr_bit; 384 1.28 thorpej } 385 1.28 thorpej 386 1.28 thorpej /* Only program the hardware if the irq is enabled. */ 387 1.28 thorpej if (dec_6600_intr_enables & intr_bit) 388 1.28 thorpej dec_6600_intr_program(pc); 389 1.1 ross } 390 1.1 ross 391 1.29 thorpej static void 392 1.29 thorpej dec_6600_intr_redistribute(void) 393 1.29 thorpej { 394 1.29 thorpej KASSERT(sioprimary != NULL); 395 1.29 thorpej 396 1.29 thorpej pci_chipset_tag_t const pc = &sioprimary->pc_pc; 397 1.29 thorpej 398 1.29 thorpej /* ISA interrupts always stay on primary. Shuffle PCI interrupts. */ 399 1.29 thorpej alpha_pci_generic_intr_redistribute(pc); 400 1.29 thorpej } 401 1.29 thorpej 402 1.26 thorpej static void * 403 1.26 thorpej dec_6600_pciide_compat_intr_establish(device_t dev, 404 1.21 dyoung const struct pci_attach_args *pa, int chan, int (*func)(void *), void *arg) 405 1.1 ross { 406 1.26 thorpej pci_chipset_tag_t const pc = pa->pa_pc; 407 1.1 ross 408 1.2 thorpej /* 409 1.26 thorpej * If this isn't the TSP that holds the PCI-ISA bridge, 410 1.26 thorpej * all bets are off. 411 1.2 thorpej */ 412 1.26 thorpej if (pc->pc_intr_v != sioprimary) 413 1.2 thorpej return (NULL); 414 1.1 ross 415 1.26 thorpej return sio_pciide_compat_intr_establish(dev, pa, chan, func, arg); 416 1.1 ross } 417