1 1.33 andvar /* $NetBSD: pci_machdep.c,v 1.33 2021/09/16 20:17:46 andvar Exp $ */ 2 1.25 thorpej 3 1.25 thorpej /*- 4 1.25 thorpej * Copyright (c) 2020 The NetBSD Foundation, Inc. 5 1.25 thorpej * All rights reserved. 6 1.25 thorpej * 7 1.25 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.25 thorpej * by Jason R. Thorpe. 9 1.25 thorpej * 10 1.25 thorpej * Redistribution and use in source and binary forms, with or without 11 1.25 thorpej * modification, are permitted provided that the following conditions 12 1.25 thorpej * are met: 13 1.25 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.25 thorpej * notice, this list of conditions and the following disclaimer. 15 1.25 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.25 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.25 thorpej * documentation and/or other materials provided with the distribution. 18 1.25 thorpej * 19 1.25 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.25 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.25 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.25 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.25 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.25 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.25 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.25 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.25 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.25 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.25 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.25 thorpej */ 31 1.1 cgd 32 1.1 cgd /* 33 1.5 cgd * Copyright (c) 1995, 1996 Carnegie-Mellon University. 34 1.3 cgd * All rights reserved. 35 1.1 cgd * 36 1.3 cgd * Author: Chris G. Demetriou 37 1.19 matt * 38 1.3 cgd * Permission to use, copy, modify and distribute this software and 39 1.3 cgd * its documentation is hereby granted, provided that both the copyright 40 1.3 cgd * notice and this permission notice appear in all copies of the 41 1.3 cgd * software, derivative works or modified versions, and any portions 42 1.3 cgd * thereof, and that both notices appear in supporting documentation. 43 1.19 matt * 44 1.19 matt * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 45 1.19 matt * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 46 1.3 cgd * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 47 1.19 matt * 48 1.3 cgd * Carnegie Mellon requests users of this software to return to 49 1.1 cgd * 50 1.3 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 51 1.3 cgd * School of Computer Science 52 1.3 cgd * Carnegie Mellon University 53 1.3 cgd * Pittsburgh PA 15213-3890 54 1.3 cgd * 55 1.3 cgd * any improvements or extensions that they make and grant Carnegie the 56 1.3 cgd * rights to redistribute these changes. 57 1.1 cgd */ 58 1.1 cgd 59 1.1 cgd /* 60 1.1 cgd * Machine-specific functions for PCI autoconfiguration. 61 1.1 cgd */ 62 1.9 cgd 63 1.10 cgd #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 64 1.10 cgd 65 1.33 andvar __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.33 2021/09/16 20:17:46 andvar Exp $"); 66 1.1 cgd 67 1.1 cgd #include <sys/types.h> 68 1.1 cgd #include <sys/param.h> 69 1.1 cgd #include <sys/time.h> 70 1.1 cgd #include <sys/systm.h> 71 1.1 cgd #include <sys/errno.h> 72 1.1 cgd #include <sys/device.h> 73 1.26 thorpej #include <sys/cpu.h> 74 1.14 mrg 75 1.1 cgd #include <dev/isa/isavar.h> 76 1.3 cgd #include <dev/pci/pcireg.h> 77 1.1 cgd #include <dev/pci/pcivar.h> 78 1.2 cgd #include <dev/pci/pcidevs.h> 79 1.1 cgd 80 1.7 cgd #include "vga_pci.h" 81 1.7 cgd #if NVGA_PCI 82 1.13 drochner #include <dev/ic/mc6845reg.h> 83 1.13 drochner #include <dev/ic/pcdisplayvar.h> 84 1.12 drochner #include <dev/pci/vga_pcivar.h> 85 1.3 cgd #endif 86 1.3 cgd 87 1.2 cgd #include "tga.h" 88 1.3 cgd #if NTGA 89 1.12 drochner #include <dev/pci/tgavar.h> 90 1.3 cgd #endif 91 1.1 cgd 92 1.20 tsutsui #include <machine/rpb.h> 93 1.20 tsutsui 94 1.1 cgd void 95 1.17 dsl pci_display_console(bus_space_tag_t iot, bus_space_tag_t memt, pci_chipset_tag_t pc, int bus, int device, int function) 96 1.1 cgd { 97 1.23 uebayasi #if NVGA_PCI || NTGA 98 1.4 cgd pcitag_t tag; 99 1.24 rin pcireg_t id; 100 1.4 cgd int match, nmatch; 101 1.23 uebayasi #endif 102 1.24 rin #if NVGA_PCI 103 1.24 rin pcireg_t class; 104 1.24 rin #endif 105 1.16 dsl int (*fn)(bus_space_tag_t, bus_space_tag_t, pci_chipset_tag_t, 106 1.16 dsl int, int, int); 107 1.1 cgd 108 1.23 uebayasi #if NVGA_PCI || NTGA 109 1.4 cgd tag = pci_make_tag(pc, bus, device, function); 110 1.4 cgd id = pci_conf_read(pc, tag, PCI_ID_REG); 111 1.2 cgd if (id == 0 || id == 0xffffffff) 112 1.2 cgd panic("pci_display_console: no device at %d/%d/%d", 113 1.2 cgd bus, device, function); 114 1.24 rin # if NVGA_PCI 115 1.4 cgd class = pci_conf_read(pc, tag, PCI_CLASS_REG); 116 1.24 rin # endif 117 1.4 cgd 118 1.23 uebayasi match = 0; 119 1.23 uebayasi #endif 120 1.4 cgd fn = NULL; 121 1.2 cgd 122 1.7 cgd #if NVGA_PCI 123 1.7 cgd nmatch = DEVICE_IS_VGA_PCI(class, id); 124 1.4 cgd if (nmatch > match) { 125 1.4 cgd match = nmatch; 126 1.12 drochner fn = vga_pci_cnattach; 127 1.2 cgd } 128 1.3 cgd #endif 129 1.2 cgd #if NTGA 130 1.4 cgd nmatch = DEVICE_IS_TGA(class, id); 131 1.15 elric if (nmatch > match) 132 1.15 elric nmatch = tga_cnmatch(iot, memt, pc, tag); 133 1.4 cgd if (nmatch > match) { 134 1.4 cgd match = nmatch; 135 1.12 drochner fn = tga_cnattach; 136 1.2 cgd } 137 1.3 cgd #endif 138 1.2 cgd 139 1.4 cgd if (fn != NULL) 140 1.6 cgd (*fn)(iot, memt, pc, bus, device, function); 141 1.4 cgd else 142 1.4 cgd panic("pci_display_console: unconfigured device at %d/%d/%d", 143 1.2 cgd bus, device, function); 144 1.1 cgd } 145 1.20 tsutsui 146 1.20 tsutsui void 147 1.20 tsutsui device_pci_register(device_t dev, void *aux) 148 1.20 tsutsui { 149 1.20 tsutsui struct pci_attach_args *pa = aux; 150 1.20 tsutsui struct ctb *ctb; 151 1.20 tsutsui prop_dictionary_t dict; 152 1.20 tsutsui 153 1.20 tsutsui /* set properties for PCI framebuffers */ 154 1.20 tsutsui ctb = (struct ctb *)(((char *)hwrpb) + hwrpb->rpb_ctb_off); 155 1.20 tsutsui if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && 156 1.20 tsutsui ctb->ctb_term_type == CTB_GRAPHICS) { 157 1.20 tsutsui /* XXX should consider multiple displays? */ 158 1.20 tsutsui dict = device_properties(dev); 159 1.20 tsutsui prop_dictionary_set_bool(dict, "is_console", true); 160 1.20 tsutsui } 161 1.20 tsutsui } 162 1.25 thorpej 163 1.29 thorpej void 164 1.29 thorpej alpha_pci_intr_init(void *core, bus_space_tag_t iot, bus_space_tag_t memt, 165 1.29 thorpej pci_chipset_tag_t pc) 166 1.29 thorpej { 167 1.29 thorpej __link_set_decl(alpha_pci_intr_impls, struct alpha_pci_intr_impl); 168 1.29 thorpej struct alpha_pci_intr_impl * const *impl; 169 1.29 thorpej 170 1.29 thorpej __link_set_foreach(impl, alpha_pci_intr_impls) { 171 1.29 thorpej if ((*impl)->systype == cputype) { 172 1.29 thorpej (*impl)->intr_init(core, iot, memt, pc); 173 1.29 thorpej return; 174 1.29 thorpej } 175 1.29 thorpej } 176 1.29 thorpej panic("%s: unknown systype %d", __func__, cputype); 177 1.29 thorpej } 178 1.29 thorpej 179 1.32 thorpej void 180 1.32 thorpej alpha_pci_intr_alloc(pci_chipset_tag_t pc, unsigned int maxstrays) 181 1.32 thorpej { 182 1.32 thorpej unsigned int i; 183 1.32 thorpej struct evcnt *ev; 184 1.32 thorpej const char *cp; 185 1.32 thorpej 186 1.32 thorpej pc->pc_shared_intrs = alpha_shared_intr_alloc(pc->pc_nirq); 187 1.32 thorpej 188 1.32 thorpej for (i = 0; i < pc->pc_nirq; i++) { 189 1.32 thorpej alpha_shared_intr_set_maxstrays(pc->pc_shared_intrs, i, 190 1.32 thorpej maxstrays); 191 1.32 thorpej alpha_shared_intr_set_private(pc->pc_shared_intrs, i, 192 1.32 thorpej pc->pc_intr_v); 193 1.32 thorpej 194 1.32 thorpej ev = alpha_shared_intr_evcnt(pc->pc_shared_intrs, i); 195 1.32 thorpej cp = alpha_shared_intr_string(pc->pc_shared_intrs, i); 196 1.32 thorpej 197 1.32 thorpej evcnt_attach_dynamic(ev, EVCNT_TYPE_INTR, NULL, 198 1.32 thorpej pc->pc_intr_desc, cp); 199 1.32 thorpej } 200 1.32 thorpej } 201 1.32 thorpej 202 1.25 thorpej int 203 1.25 thorpej alpha_pci_generic_intr_map(const struct pci_attach_args * const pa, 204 1.25 thorpej pci_intr_handle_t * const ihp) 205 1.25 thorpej { 206 1.25 thorpej pcitag_t const bustag = pa->pa_intrtag; 207 1.25 thorpej int const buspin = pa->pa_intrpin; 208 1.25 thorpej int const line = pa->pa_intrline; 209 1.25 thorpej pci_chipset_tag_t const pc = pa->pa_pc; 210 1.25 thorpej int bus, device, function; 211 1.25 thorpej 212 1.25 thorpej if (buspin == 0) { 213 1.25 thorpej /* No IRQ used. */ 214 1.25 thorpej return 1; 215 1.25 thorpej } 216 1.25 thorpej if (buspin < 0 || buspin > 4) { 217 1.25 thorpej printf("%s: bad interrupt pin %d\n", __func__, buspin); 218 1.25 thorpej return 1; 219 1.25 thorpej } 220 1.25 thorpej 221 1.25 thorpej pci_decompose_tag(pc, bustag, &bus, &device, &function); 222 1.25 thorpej 223 1.25 thorpej /* 224 1.25 thorpej * The console firmware places the interrupt mapping in the "line" 225 1.25 thorpej * value. A valaue of (char)-1 indicates there is no mapping. 226 1.25 thorpej */ 227 1.25 thorpej if (line == 0xff) { 228 1.25 thorpej printf("%s: no mapping for %d/%d/%d\n", __func__, 229 1.25 thorpej bus, device, function); 230 1.25 thorpej return 1; 231 1.25 thorpej } 232 1.25 thorpej 233 1.25 thorpej if (line < 0 || line >= pc->pc_nirq) { 234 1.25 thorpej printf("%s: bad line %d for %d/%d/%d\n", __func__, 235 1.25 thorpej line, bus, device, function); 236 1.25 thorpej return 1; 237 1.25 thorpej } 238 1.25 thorpej 239 1.25 thorpej alpha_pci_intr_handle_init(ihp, line, 0); 240 1.25 thorpej return 0; 241 1.25 thorpej } 242 1.25 thorpej 243 1.25 thorpej const char * 244 1.25 thorpej alpha_pci_generic_intr_string(pci_chipset_tag_t const pc, 245 1.25 thorpej pci_intr_handle_t const ih, char * const buf, size_t const len) 246 1.25 thorpej { 247 1.25 thorpej const u_int irq = alpha_pci_intr_handle_get_irq(&ih); 248 1.25 thorpej 249 1.25 thorpej KASSERT(irq < pc->pc_nirq); 250 1.25 thorpej 251 1.31 thorpej snprintf(buf, len, "%s irq %u", pc->pc_intr_desc, irq); 252 1.25 thorpej return buf; 253 1.25 thorpej } 254 1.25 thorpej 255 1.25 thorpej const struct evcnt * 256 1.25 thorpej alpha_pci_generic_intr_evcnt(pci_chipset_tag_t const pc, 257 1.25 thorpej pci_intr_handle_t const ih) 258 1.25 thorpej { 259 1.25 thorpej const u_int irq = alpha_pci_intr_handle_get_irq(&ih); 260 1.25 thorpej 261 1.25 thorpej KASSERT(irq < pc->pc_nirq); 262 1.25 thorpej 263 1.25 thorpej return alpha_shared_intr_evcnt(pc->pc_shared_intrs, irq); 264 1.25 thorpej } 265 1.25 thorpej 266 1.27 thorpej static struct cpu_info * 267 1.27 thorpej alpha_pci_generic_intr_select_cpu(pci_chipset_tag_t const pc, u_int const irq, 268 1.27 thorpej u_int const flags) 269 1.27 thorpej { 270 1.27 thorpej struct cpu_info *ci, *best_ci; 271 1.27 thorpej CPU_INFO_ITERATOR cii; 272 1.27 thorpej 273 1.27 thorpej KASSERT(mutex_owned(&cpu_lock)); 274 1.27 thorpej 275 1.27 thorpej /* 276 1.27 thorpej * If the back-end didn't tell us where we can route, then 277 1.33 andvar * they all go to the primary CPU. 278 1.27 thorpej */ 279 1.27 thorpej if (pc->pc_eligible_cpus == 0) { 280 1.27 thorpej return &cpu_info_primary; 281 1.27 thorpej } 282 1.27 thorpej 283 1.27 thorpej /* 284 1.27 thorpej * If the interrupt already has a CPU assigned, keep on using it, 285 1.27 thorpej * unless the CPU has become ineligible. 286 1.27 thorpej */ 287 1.27 thorpej ci = alpha_shared_intr_get_cpu(pc->pc_shared_intrs, irq); 288 1.27 thorpej if (ci != NULL) { 289 1.27 thorpej if ((ci->ci_schedstate.spc_flags & SPCF_NOINTR) == 0 || 290 1.27 thorpej CPU_IS_PRIMARY(ci)) { 291 1.27 thorpej return ci; 292 1.27 thorpej } 293 1.27 thorpej } 294 1.27 thorpej 295 1.27 thorpej /* 296 1.27 thorpej * Pick the CPU with the fewest handlers. 297 1.27 thorpej */ 298 1.27 thorpej best_ci = NULL; 299 1.27 thorpej for (CPU_INFO_FOREACH(cii, ci)) { 300 1.27 thorpej if ((pc->pc_eligible_cpus & __BIT(ci->ci_cpuid)) == 0) { 301 1.27 thorpej /* This CPU is not eligible in hardware. */ 302 1.27 thorpej continue; 303 1.27 thorpej } 304 1.27 thorpej if (ci->ci_schedstate.spc_flags & SPCF_NOINTR) { 305 1.27 thorpej /* This CPU is not eligible in software. */ 306 1.27 thorpej continue; 307 1.27 thorpej } 308 1.27 thorpej if (best_ci == NULL || 309 1.27 thorpej ci->ci_nintrhand < best_ci->ci_nintrhand) { 310 1.27 thorpej best_ci = ci; 311 1.27 thorpej } 312 1.27 thorpej } 313 1.27 thorpej 314 1.27 thorpej /* If we found one, cool... */ 315 1.27 thorpej if (best_ci != NULL) { 316 1.27 thorpej return best_ci; 317 1.27 thorpej } 318 1.27 thorpej 319 1.27 thorpej /* ...if not, well I guess we'll just fall back on the primary. */ 320 1.27 thorpej return &cpu_info_primary; 321 1.27 thorpej } 322 1.27 thorpej 323 1.25 thorpej void * 324 1.25 thorpej alpha_pci_generic_intr_establish(pci_chipset_tag_t const pc, 325 1.25 thorpej pci_intr_handle_t const ih, int const level, 326 1.25 thorpej int (*func)(void *), void *arg) 327 1.25 thorpej { 328 1.25 thorpej const u_int irq = alpha_pci_intr_handle_get_irq(&ih); 329 1.25 thorpej const u_int flags = alpha_pci_intr_handle_get_flags(&ih); 330 1.25 thorpej void *cookie; 331 1.25 thorpej 332 1.25 thorpej KASSERT(irq < pc->pc_nirq); 333 1.25 thorpej 334 1.26 thorpej cookie = alpha_shared_intr_alloc_intrhand(pc->pc_shared_intrs, 335 1.25 thorpej irq, IST_LEVEL, level, flags, func, arg, pc->pc_intr_desc); 336 1.25 thorpej 337 1.26 thorpej if (cookie == NULL) 338 1.26 thorpej return NULL; 339 1.26 thorpej 340 1.26 thorpej mutex_enter(&cpu_lock); 341 1.26 thorpej 342 1.27 thorpej struct cpu_info *target_ci = 343 1.27 thorpej alpha_pci_generic_intr_select_cpu(pc, irq, flags); 344 1.27 thorpej struct cpu_info *current_ci = 345 1.27 thorpej alpha_shared_intr_get_cpu(pc->pc_shared_intrs, irq); 346 1.27 thorpej 347 1.27 thorpej const bool first_handler = 348 1.27 thorpej ! alpha_shared_intr_isactive(pc->pc_shared_intrs, irq); 349 1.27 thorpej 350 1.27 thorpej /* 351 1.27 thorpej * If this is the first handler on this interrupt, or if the 352 1.27 thorpej * target CPU has changed, then program the route if the 353 1.27 thorpej * hardware supports it. 354 1.27 thorpej */ 355 1.27 thorpej if (first_handler || target_ci != current_ci) { 356 1.27 thorpej alpha_shared_intr_set_cpu(pc->pc_shared_intrs, irq, target_ci); 357 1.27 thorpej if (pc->pc_intr_set_affinity != NULL) { 358 1.27 thorpej pc->pc_intr_set_affinity(pc, irq, target_ci); 359 1.27 thorpej } 360 1.27 thorpej } 361 1.27 thorpej 362 1.26 thorpej if (! alpha_shared_intr_link(pc->pc_shared_intrs, cookie, 363 1.26 thorpej pc->pc_intr_desc)) { 364 1.26 thorpej mutex_exit(&cpu_lock); 365 1.26 thorpej alpha_shared_intr_free_intrhand(cookie); 366 1.26 thorpej return NULL; 367 1.26 thorpej } 368 1.26 thorpej 369 1.27 thorpej if (first_handler) { 370 1.25 thorpej scb_set(pc->pc_vecbase + SCB_IDXTOVEC(irq), 371 1.25 thorpej alpha_pci_generic_iointr, pc); 372 1.25 thorpej pc->pc_intr_enable(pc, irq); 373 1.25 thorpej } 374 1.26 thorpej 375 1.26 thorpej mutex_exit(&cpu_lock); 376 1.26 thorpej 377 1.25 thorpej return cookie; 378 1.25 thorpej } 379 1.25 thorpej 380 1.25 thorpej void 381 1.25 thorpej alpha_pci_generic_intr_disestablish(pci_chipset_tag_t const pc, 382 1.25 thorpej void * const cookie) 383 1.25 thorpej { 384 1.25 thorpej struct alpha_shared_intrhand * const ih = cookie; 385 1.25 thorpej const u_int irq = ih->ih_num; 386 1.25 thorpej 387 1.26 thorpej mutex_enter(&cpu_lock); 388 1.25 thorpej 389 1.26 thorpej if (alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { 390 1.25 thorpej pc->pc_intr_disable(pc, irq); 391 1.25 thorpej alpha_shared_intr_set_dfltsharetype(pc->pc_shared_intrs, 392 1.25 thorpej irq, IST_NONE); 393 1.25 thorpej scb_free(pc->pc_vecbase + SCB_IDXTOVEC(irq)); 394 1.25 thorpej } 395 1.25 thorpej 396 1.26 thorpej alpha_shared_intr_unlink(pc->pc_shared_intrs, cookie, pc->pc_intr_desc); 397 1.26 thorpej 398 1.26 thorpej mutex_exit(&cpu_lock); 399 1.26 thorpej 400 1.26 thorpej alpha_shared_intr_free_intrhand(cookie); 401 1.25 thorpej } 402 1.25 thorpej 403 1.25 thorpej void 404 1.25 thorpej alpha_pci_generic_iointr(void * const arg, unsigned long const vec) 405 1.25 thorpej { 406 1.25 thorpej pci_chipset_tag_t const pc = arg; 407 1.25 thorpej const u_int irq = SCB_VECTOIDX(vec - pc->pc_vecbase); 408 1.25 thorpej 409 1.25 thorpej if (!alpha_shared_intr_dispatch(pc->pc_shared_intrs, irq)) { 410 1.25 thorpej alpha_shared_intr_stray(pc->pc_shared_intrs, irq, 411 1.25 thorpej pc->pc_intr_desc); 412 1.25 thorpej if (ALPHA_SHARED_INTR_DISABLE(pc->pc_shared_intrs, irq)) { 413 1.25 thorpej pc->pc_intr_disable(pc, irq); 414 1.25 thorpej } 415 1.25 thorpej } else { 416 1.25 thorpej alpha_shared_intr_reset_strays(pc->pc_shared_intrs, irq); 417 1.25 thorpej } 418 1.25 thorpej } 419 1.25 thorpej 420 1.28 thorpej void 421 1.28 thorpej alpha_pci_generic_intr_redistribute(pci_chipset_tag_t const pc) 422 1.28 thorpej { 423 1.28 thorpej struct cpu_info *current_ci, *new_ci; 424 1.28 thorpej unsigned int irq; 425 1.28 thorpej 426 1.28 thorpej KASSERT(mutex_owned(&cpu_lock)); 427 1.28 thorpej KASSERT(mp_online); 428 1.28 thorpej 429 1.28 thorpej /* If we can't set affinity, then there's nothing to do. */ 430 1.28 thorpej if (pc->pc_eligible_cpus == 0 || pc->pc_intr_set_affinity == NULL) { 431 1.28 thorpej return; 432 1.28 thorpej } 433 1.28 thorpej 434 1.28 thorpej /* 435 1.28 thorpej * Look at each IRQ, and allocate a new CPU for each IRQ 436 1.28 thorpej * that's being serviced by a now-shielded CPU. 437 1.28 thorpej */ 438 1.28 thorpej for (irq = 0; irq < pc->pc_nirq; irq++) { 439 1.28 thorpej current_ci = 440 1.28 thorpej alpha_shared_intr_get_cpu(pc->pc_shared_intrs, irq); 441 1.28 thorpej if (current_ci == NULL || 442 1.28 thorpej (current_ci->ci_schedstate.spc_flags & SPCF_NOINTR) == 0) { 443 1.28 thorpej continue; 444 1.28 thorpej } 445 1.28 thorpej 446 1.28 thorpej new_ci = alpha_pci_generic_intr_select_cpu(pc, irq, 0); 447 1.28 thorpej if (new_ci == current_ci) { 448 1.28 thorpej /* Can't shield this one. */ 449 1.28 thorpej continue; 450 1.28 thorpej } 451 1.28 thorpej 452 1.28 thorpej alpha_shared_intr_set_cpu(pc->pc_shared_intrs, irq, new_ci); 453 1.28 thorpej pc->pc_intr_set_affinity(pc, irq, new_ci); 454 1.28 thorpej } 455 1.28 thorpej 456 1.28 thorpej /* XXX should now re-balance */ 457 1.28 thorpej } 458 1.28 thorpej 459 1.25 thorpej #define ALPHA_PCI_INTR_HANDLE_IRQ __BITS(0,31) 460 1.25 thorpej #define ALPHA_PCI_INTR_HANDLE_FLAGS __BITS(32,63) 461 1.25 thorpej 462 1.25 thorpej void 463 1.25 thorpej alpha_pci_intr_handle_init(pci_intr_handle_t * const ihp, u_int const irq, 464 1.25 thorpej u_int const flags) 465 1.25 thorpej { 466 1.25 thorpej ihp->value = __SHIFTIN(irq, ALPHA_PCI_INTR_HANDLE_IRQ) | 467 1.25 thorpej __SHIFTIN(flags, ALPHA_PCI_INTR_HANDLE_FLAGS); 468 1.25 thorpej } 469 1.25 thorpej 470 1.25 thorpej void 471 1.25 thorpej alpha_pci_intr_handle_set_irq(pci_intr_handle_t * const ihp, u_int const irq) 472 1.25 thorpej { 473 1.25 thorpej ihp->value = (ihp->value & ALPHA_PCI_INTR_HANDLE_FLAGS) | 474 1.25 thorpej __SHIFTIN(irq, ALPHA_PCI_INTR_HANDLE_IRQ); 475 1.25 thorpej } 476 1.25 thorpej 477 1.25 thorpej u_int 478 1.25 thorpej alpha_pci_intr_handle_get_irq(const pci_intr_handle_t * const ihp) 479 1.25 thorpej { 480 1.25 thorpej return __SHIFTOUT(ihp->value, ALPHA_PCI_INTR_HANDLE_IRQ); 481 1.25 thorpej } 482 1.25 thorpej 483 1.25 thorpej void 484 1.25 thorpej alpha_pci_intr_handle_set_flags(pci_intr_handle_t * const ihp, 485 1.25 thorpej u_int const flags) 486 1.25 thorpej { 487 1.25 thorpej ihp->value = (ihp->value & ALPHA_PCI_INTR_HANDLE_IRQ) | 488 1.25 thorpej __SHIFTIN(flags, ALPHA_PCI_INTR_HANDLE_FLAGS); 489 1.25 thorpej } 490 1.25 thorpej 491 1.25 thorpej u_int 492 1.25 thorpej alpha_pci_intr_handle_get_flags(const pci_intr_handle_t * const ihp) 493 1.25 thorpej { 494 1.25 thorpej return __SHIFTOUT(ihp->value, ALPHA_PCI_INTR_HANDLE_FLAGS); 495 1.25 thorpej } 496 1.25 thorpej 497 1.25 thorpej /* 498 1.25 thorpej * MI PCI back-end entry points. 499 1.25 thorpej */ 500 1.25 thorpej 501 1.25 thorpej void 502 1.25 thorpej pci_attach_hook(device_t const parent, device_t const self, 503 1.25 thorpej struct pcibus_attach_args * const pba) 504 1.25 thorpej { 505 1.25 thorpej pci_chipset_tag_t const pc = pba->pba_pc; 506 1.25 thorpej 507 1.30 thorpej if (pc->pc_attach_hook != NULL) { 508 1.30 thorpej pc->pc_attach_hook(parent, self, pba); 509 1.30 thorpej } 510 1.25 thorpej } 511 1.25 thorpej 512 1.25 thorpej int 513 1.25 thorpej pci_bus_maxdevs(pci_chipset_tag_t const pc, int const busno) 514 1.25 thorpej { 515 1.30 thorpej if (pc->pc_bus_maxdevs == NULL) { 516 1.30 thorpej return 32; 517 1.30 thorpej } 518 1.30 thorpej 519 1.25 thorpej return pc->pc_bus_maxdevs(pc->pc_conf_v, busno); 520 1.25 thorpej } 521 1.25 thorpej 522 1.25 thorpej pcitag_t 523 1.25 thorpej pci_make_tag(pci_chipset_tag_t const pc, int const bus, int const dev, 524 1.25 thorpej int const func) 525 1.25 thorpej { 526 1.30 thorpej if (__predict_true(pc->pc_make_tag == NULL)) { 527 1.30 thorpej /* Just use the standard Type 1 address format. */ 528 1.30 thorpej return __SHIFTIN(bus, PCI_CONF_TYPE1_BUS) | 529 1.30 thorpej __SHIFTIN(dev, PCI_CONF_TYPE1_DEVICE) | 530 1.30 thorpej __SHIFTIN(func, PCI_CONF_TYPE1_FUNCTION); 531 1.30 thorpej } 532 1.30 thorpej 533 1.25 thorpej return pc->pc_make_tag(pc->pc_conf_v, bus, dev, func); 534 1.25 thorpej } 535 1.25 thorpej 536 1.25 thorpej void 537 1.25 thorpej pci_decompose_tag(pci_chipset_tag_t const pc, pcitag_t const tag, 538 1.25 thorpej int * const busp, int * const devp, int * const funcp) 539 1.25 thorpej { 540 1.30 thorpej if (__predict_true(pc->pc_decompose_tag == NULL)) { 541 1.30 thorpej if (busp != NULL) 542 1.30 thorpej *busp = __SHIFTOUT(tag, PCI_CONF_TYPE1_BUS); 543 1.30 thorpej if (devp != NULL) 544 1.30 thorpej *devp = __SHIFTOUT(tag, PCI_CONF_TYPE1_DEVICE); 545 1.30 thorpej if (funcp != NULL) 546 1.30 thorpej *funcp = __SHIFTOUT(tag, PCI_CONF_TYPE1_FUNCTION); 547 1.30 thorpej return; 548 1.30 thorpej } 549 1.30 thorpej 550 1.25 thorpej pc->pc_decompose_tag(pc->pc_conf_v, tag, busp, devp, funcp); 551 1.25 thorpej } 552 1.25 thorpej 553 1.25 thorpej pcireg_t 554 1.25 thorpej pci_conf_read(pci_chipset_tag_t const pc, pcitag_t const tag, int const reg) 555 1.25 thorpej { 556 1.25 thorpej KASSERT(pc->pc_conf_read != NULL); 557 1.25 thorpej return pc->pc_conf_read(pc->pc_conf_v, tag, reg); 558 1.25 thorpej } 559 1.25 thorpej 560 1.25 thorpej void 561 1.25 thorpej pci_conf_write(pci_chipset_tag_t const pc, pcitag_t const tag, int const reg, 562 1.25 thorpej pcireg_t const val) 563 1.25 thorpej { 564 1.25 thorpej KASSERT(pc->pc_conf_write != NULL); 565 1.25 thorpej pc->pc_conf_write(pc->pc_conf_v, tag, reg, val); 566 1.25 thorpej } 567 1.25 thorpej 568 1.25 thorpej int 569 1.25 thorpej pci_intr_map(const struct pci_attach_args * const pa, 570 1.25 thorpej pci_intr_handle_t * const ihp) 571 1.25 thorpej { 572 1.25 thorpej pci_chipset_tag_t const pc = pa->pa_pc; 573 1.25 thorpej 574 1.25 thorpej KASSERT(pc->pc_intr_map != NULL); 575 1.25 thorpej return pc->pc_intr_map(pa, ihp); 576 1.25 thorpej } 577 1.25 thorpej 578 1.25 thorpej const char * 579 1.25 thorpej pci_intr_string(pci_chipset_tag_t const pc, pci_intr_handle_t const ih, 580 1.25 thorpej char * const buf, size_t const len) 581 1.25 thorpej { 582 1.25 thorpej KASSERT(pc->pc_intr_string != NULL); 583 1.25 thorpej return pc->pc_intr_string(pc, ih, buf, len); 584 1.25 thorpej } 585 1.25 thorpej 586 1.25 thorpej const struct evcnt * 587 1.25 thorpej pci_intr_evcnt(pci_chipset_tag_t const pc, pci_intr_handle_t const ih) 588 1.25 thorpej { 589 1.25 thorpej KASSERT(pc->pc_intr_evcnt != NULL); 590 1.25 thorpej return pc->pc_intr_evcnt(pc, ih); 591 1.25 thorpej } 592 1.25 thorpej 593 1.25 thorpej void * 594 1.25 thorpej pci_intr_establish(pci_chipset_tag_t const pc, pci_intr_handle_t const ih, 595 1.25 thorpej int const ipl, int (*func)(void *), void *arg) 596 1.25 thorpej { 597 1.25 thorpej KASSERT(pc->pc_intr_establish != NULL); 598 1.25 thorpej return pc->pc_intr_establish(pc, ih, ipl, func, arg); 599 1.25 thorpej } 600 1.25 thorpej 601 1.25 thorpej void 602 1.25 thorpej pci_intr_disestablish(pci_chipset_tag_t const pc, void * const cookie) 603 1.25 thorpej { 604 1.25 thorpej KASSERT(pc->pc_intr_disestablish != NULL); 605 1.25 thorpej pc->pc_intr_disestablish(pc, cookie); 606 1.25 thorpej } 607 1.25 thorpej 608 1.25 thorpej int 609 1.25 thorpej pci_intr_setattr(pci_chipset_tag_t const pc __unused, 610 1.25 thorpej pci_intr_handle_t * const ihp, int const attr, uint64_t const data) 611 1.25 thorpej { 612 1.25 thorpej u_int flags = alpha_pci_intr_handle_get_flags(ihp); 613 1.25 thorpej 614 1.25 thorpej switch (attr) { 615 1.25 thorpej case PCI_INTR_MPSAFE: 616 1.25 thorpej if (data) 617 1.25 thorpej flags |= ALPHA_INTR_MPSAFE; 618 1.25 thorpej else 619 1.25 thorpej flags &= ~ALPHA_INTR_MPSAFE; 620 1.25 thorpej break; 621 1.25 thorpej 622 1.25 thorpej default: 623 1.25 thorpej return ENODEV; 624 1.25 thorpej } 625 1.25 thorpej 626 1.25 thorpej alpha_pci_intr_handle_set_flags(ihp, flags); 627 1.25 thorpej return 0; 628 1.25 thorpej } 629