Lines Matching +full:irq +full:- +full:device
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
52 * A link device. Loosely based on the ACPI PCI link device. This doesn't
67 int device; member
74 int device; member
82 static int pci_pir_biosroute(int bus, int device, int func, int pin,
83 int irq);
94 static uint8_t pci_pir_search_irq(int bus, int device, int pin);
95 static int pci_pir_valid_irq(struct pci_link *pci_link, int irq);
146 /* XXX - Use pmap_mapdev()? */ in pci_pir_open()
148 if (pt->pt_header.ph_length <= sizeof(struct PIR_header)) in pci_pir_open()
151 i < (pt->pt_header.ph_length); i++) in pci_pir_open()
158 pci_route_count = (pt->pt_header.ph_length - in pci_pir_open()
172 if (pci_link->pl_id == link_id) in pci_pir_find_link()
179 * Find the link device associated with a PCI device in the table.
188 if (entry->pe_bus == lookup->bus && in pci_pir_find_link_handler()
189 entry->pe_device == lookup->device && in pci_pir_find_link_handler()
190 intpin - entry->pe_intpin == lookup->pin) in pci_pir_find_link_handler()
191 *lookup->pci_link_ptr = pci_pir_find_link(intpin->link); in pci_pir_find_link_handler()
195 * Check to see if a possible IRQ setting is valid.
198 pci_pir_valid_irq(struct pci_link *pci_link, int irq) in pci_pir_valid_irq() argument
201 if (!PCI_INTERRUPT_VALID(irq)) in pci_pir_valid_irq()
203 return (pci_link->pl_irqmask & (1 << irq)); in pci_pir_valid_irq()
218 entry = &pci_route_table->pt_entry[0]; in pci_pir_walk_table()
220 intpin = &entry->pe_intpin[0]; in pci_pir_walk_table()
222 if (intpin->link != 0) in pci_pir_walk_table()
233 pci_link = pci_pir_find_link(intpin->link); in pci_pir_create_links()
235 pci_link->pl_references++; in pci_pir_create_links()
236 if (intpin->irqs != pci_link->pl_irqmask) { in pci_pir_create_links()
240 entry->pe_bus, entry->pe_device, in pci_pir_create_links()
241 (intpin - entry->pe_intpin) + 'A', in pci_pir_create_links()
242 pci_link->pl_id); in pci_pir_create_links()
243 pci_link->pl_irqmask &= intpin->irqs; in pci_pir_create_links()
247 pci_link->pl_id = intpin->link; in pci_pir_create_links()
248 pci_link->pl_irqmask = intpin->irqs; in pci_pir_create_links()
249 pci_link->pl_irq = PCI_INVALID_IRQ; in pci_pir_create_links()
250 pci_link->pl_references = 1; in pci_pir_create_links()
251 pci_link->pl_routed = 0; in pci_pir_create_links()
257 * Look to see if any of the functions on the PCI device at bus/device
261 pci_pir_search_irq(int bus, int device, int pin) in pci_pir_search_irq() argument
266 /* See if we have a valid device at function 0. */ in pci_pir_search_irq()
267 value = pci_cfgregread(0, bus, device, 0, PCIR_VENDOR, 2); in pci_pir_search_irq()
270 value = pci_cfgregread(0, bus, device, 0, PCIR_HDRTYPE, 1); in pci_pir_search_irq()
278 /* Scan all possible functions at this device. */ in pci_pir_search_irq()
280 value = pci_cfgregread(0, bus, device, func, PCIR_VENDOR, 2); in pci_pir_search_irq()
283 value = pci_cfgregread(0, bus, device, func, PCIR_INTPIN, 1); in pci_pir_search_irq()
292 value = pci_cfgregread(0, bus, device, func, PCIR_INTLINE, 1); in pci_pir_search_irq()
296 bus, device, pin + 'A', func, value); in pci_pir_search_irq()
304 * Try to initialize IRQ based on this device's IRQ.
311 uint8_t irq, pin; in pci_pir_initial_irqs() local
313 pin = intpin - entry->pe_intpin; in pci_pir_initial_irqs()
314 pci_link = pci_pir_find_link(intpin->link); in pci_pir_initial_irqs()
315 irq = pci_pir_search_irq(entry->pe_bus, entry->pe_device, pin); in pci_pir_initial_irqs()
316 if (irq == PCI_INVALID_IRQ || irq == pci_link->pl_irq) in pci_pir_initial_irqs()
320 if (irq >= NUM_ISA_INTERRUPTS) { in pci_pir_initial_irqs()
322 "$PIR: Ignoring invalid BIOS IRQ %d from %d.%d.INT%c for link %#x\n", in pci_pir_initial_irqs()
323 irq, entry->pe_bus, entry->pe_device, pin + 'A', in pci_pir_initial_irqs()
324 pci_link->pl_id); in pci_pir_initial_irqs()
329 * If we don't have an IRQ for this link yet, then we trust the in pci_pir_initial_irqs()
332 if (pci_link->pl_irq == PCI_INVALID_IRQ) { in pci_pir_initial_irqs()
333 if (!pci_pir_valid_irq(pci_link, irq)) in pci_pir_initial_irqs()
335 "$PIR: Using invalid BIOS IRQ %d from %d.%d.INT%c for link %#x\n", in pci_pir_initial_irqs()
336 irq, entry->pe_bus, entry->pe_device, pin + 'A', in pci_pir_initial_irqs()
337 pci_link->pl_id); in pci_pir_initial_irqs()
338 pci_link->pl_irq = irq; in pci_pir_initial_irqs()
339 pci_link->pl_routed = 1; in pci_pir_initial_irqs()
344 * We have an IRQ and it doesn't match the current IRQ for this in pci_pir_initial_irqs()
345 * link. If the new IRQ is invalid, then warn about it and ignore in pci_pir_initial_irqs()
346 * it. If the old IRQ is invalid and the new IRQ is valid, then in pci_pir_initial_irqs()
347 * prefer the new IRQ instead. If both IRQs are valid, then just in pci_pir_initial_irqs()
352 if (!pci_pir_valid_irq(pci_link, irq)) { in pci_pir_initial_irqs()
354 "$PIR: BIOS IRQ %d for %d.%d.INT%c is not valid for link %#x\n", in pci_pir_initial_irqs()
355 irq, entry->pe_bus, entry->pe_device, pin + 'A', in pci_pir_initial_irqs()
356 pci_link->pl_id); in pci_pir_initial_irqs()
357 } else if (!pci_pir_valid_irq(pci_link, pci_link->pl_irq)) { in pci_pir_initial_irqs()
359 "$PIR: Preferring valid BIOS IRQ %d from %d.%d.INT%c for link %#x to IRQ %d\n", in pci_pir_initial_irqs()
360 irq, entry->pe_bus, entry->pe_device, pin + 'A', in pci_pir_initial_irqs()
361 pci_link->pl_id, pci_link->pl_irq); in pci_pir_initial_irqs()
362 pci_link->pl_irq = irq; in pci_pir_initial_irqs()
363 pci_link->pl_routed = 1; in pci_pir_initial_irqs()
366 "$PIR: BIOS IRQ %d for %d.%d.INT%c does not match link %#x irq %d\n", in pci_pir_initial_irqs()
367 irq, entry->pe_bus, entry->pe_device, pin + 'A', in pci_pir_initial_irqs()
368 pci_link->pl_id, pci_link->pl_irq); in pci_pir_initial_irqs()
374 * various interrupt routers as they could read the initial IRQ for each
382 int i, irq; in pci_pir_parse() local
399 * checking each device connected to each link to see if it has a in pci_pir_parse()
400 * valid IRQ. in pci_pir_parse()
404 printf("$PIR: Links after initial IRQ discovery:\n"); in pci_pir_parse()
409 * Allow the user to override the IRQ for a given link device. We in pci_pir_parse()
410 * allow invalid IRQs to be specified but warn about them. An IRQ in pci_pir_parse()
411 * of 255 or 0 clears any preset IRQ. in pci_pir_parse()
416 "hw.pci.link.%#x.irq", pci_link->pl_id); in pci_pir_parse()
417 if (getenv_int(tunable_buffer, &irq) == 0) in pci_pir_parse()
419 if (irq == 0) in pci_pir_parse()
420 irq = PCI_INVALID_IRQ; in pci_pir_parse()
421 if (irq != PCI_INVALID_IRQ && in pci_pir_parse()
422 !pci_pir_valid_irq(pci_link, irq) && bootverbose) in pci_pir_parse()
424 "$PIR: Warning, IRQ %d for link %#x is not listed as valid\n", in pci_pir_parse()
425 irq, pci_link->pl_id); in pci_pir_parse()
426 pci_link->pl_routed = 0; in pci_pir_parse()
427 pci_link->pl_irq = irq; in pci_pir_parse()
436 * Build initial interrupt weights as well as bitmap of "known-good" in pci_pir_parse()
440 if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) in pci_pir_parse()
442 pir_bios_irqs |= 1 << pci_link->pl_irq; in pci_pir_parse()
443 pir_interrupt_weight[pci_link->pl_irq] += in pci_pir_parse()
444 pci_link->pl_references; in pci_pir_parse()
461 * Use the PCI BIOS to route an interrupt for a given device.
466 * BL = device [7:3] / function [2:0]
467 * CH = IRQ
471 pci_pir_biosroute(int bus, int device, int func, int pin, int irq) in pci_pir_biosroute() argument
476 args.ebx = (bus << 8) | (device << 3) | func; in pci_pir_biosroute()
477 args.ecx = (irq << 8) | (0xa + pin); in pci_pir_biosroute()
482 * Route a PCI interrupt using a link device from the $PIR.
485 pci_pir_route_interrupt(int bus, int device, int func, int pin) in pci_pir_route_interrupt() argument
489 int error, irq; in pci_pir_route_interrupt() local
494 /* Lookup link device for this PCI device/pin. */ in pci_pir_route_interrupt()
497 lookup.device = device; in pci_pir_route_interrupt()
498 lookup.pin = pin - 1; in pci_pir_route_interrupt()
503 device, pin - 1 + 'A'); in pci_pir_route_interrupt()
510 * this link only has one valid IRQ, use that. Second, we in pci_pir_route_interrupt()
512 * we check the set of known-good interrupts that the BIOS has in pci_pir_route_interrupt()
516 if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) { in pci_pir_route_interrupt()
517 if (pci_link->pl_irqmask != 0 && powerof2(pci_link->pl_irqmask)) in pci_pir_route_interrupt()
518 irq = ffs(pci_link->pl_irqmask) - 1; in pci_pir_route_interrupt()
520 irq = pci_pir_choose_irq(pci_link, in pci_pir_route_interrupt()
521 pci_route_table->pt_header.ph_pci_irqs); in pci_pir_route_interrupt()
522 if (!PCI_INTERRUPT_VALID(irq)) in pci_pir_route_interrupt()
523 irq = pci_pir_choose_irq(pci_link, pir_bios_irqs); in pci_pir_route_interrupt()
524 if (!PCI_INTERRUPT_VALID(irq)) in pci_pir_route_interrupt()
525 irq = pci_pir_choose_irq(pci_link, in pci_pir_route_interrupt()
527 if (!PCI_INTERRUPT_VALID(irq)) { in pci_pir_route_interrupt()
531 bus, device, pin - 1 + 'A'); in pci_pir_route_interrupt()
534 pci_link->pl_irq = irq; in pci_pir_route_interrupt()
537 /* Ask the BIOS to route this IRQ if we haven't done so already. */ in pci_pir_route_interrupt()
538 if (!pci_link->pl_routed) { in pci_pir_route_interrupt()
539 error = pci_pir_biosroute(bus, device, func, pin - 1, in pci_pir_route_interrupt()
540 pci_link->pl_irq); in pci_pir_route_interrupt()
543 if (error && !powerof2(pci_link->pl_irqmask)) { in pci_pir_route_interrupt()
547 pci_link->pl_routed = 1; in pci_pir_route_interrupt()
550 KASSERT(pir_device != NULL, ("missing pir device")); in pci_pir_route_interrupt()
551 BUS_CONFIG_INTR(pir_device, pci_link->pl_irq, in pci_pir_route_interrupt()
555 printf("$PIR: %d:%d INT%c routed to irq %d\n", bus, device, in pci_pir_route_interrupt()
556 pin - 1 + 'A', pci_link->pl_irq); in pci_pir_route_interrupt()
557 return (pci_link->pl_irq); in pci_pir_route_interrupt()
567 int i, irq, realmask; in pci_pir_choose_irq() local
570 realmask = pci_link->pl_irqmask & irqmask; in pci_pir_choose_irq()
574 /* Find IRQ with lowest weight. */ in pci_pir_choose_irq()
575 irq = PCI_INVALID_IRQ; in pci_pir_choose_irq()
579 if (irq == PCI_INVALID_IRQ || in pci_pir_choose_irq()
580 pir_interrupt_weight[i] < pir_interrupt_weight[irq]) in pci_pir_choose_irq()
581 irq = i; in pci_pir_choose_irq()
583 if (bootverbose && PCI_INTERRUPT_VALID(irq)) { in pci_pir_choose_irq()
584 printf("$PIR: Found IRQ %d for link %#x from ", irq, in pci_pir_choose_irq()
585 pci_link->pl_id); in pci_pir_choose_irq()
589 return (irq); in pci_pir_choose_irq()
620 printf("Link IRQ Rtd Ref IRQs\n"); in pci_pir_dump_links()
622 printf("%#4x %3d %c %3d ", pci_link->pl_id, in pci_pir_dump_links()
623 pci_link->pl_irq, pci_link->pl_routed ? 'Y' : 'N', in pci_pir_dump_links()
624 pci_link->pl_references); in pci_pir_dump_links()
625 pci_print_irqmask(pci_link->pl_irqmask); in pci_pir_dump_links()
633 * are probing a PCI-PCI bridge, then require_parse will be true and we should
634 * only succeed if a host-PCI bridge has already attached and parsed the PIR.
644 if (pci_route_table->pt_entry[i].pe_bus == bus) in pci_pir_probe()
650 * The driver for the new-bus pseudo device pir0 for the $PIR table.
678 if (intpin->link != pd->link || pd->bus != -1) in pir_resume_find_device()
680 pd->bus = entry->pe_bus; in pir_resume_find_device()
681 pd->device = entry->pe_device; in pir_resume_find_device()
682 pd->pin = intpin - entry->pe_intpin; in pir_resume_find_device()
692 /* Ask the BIOS to re-route each link that was already routed. */ in pir_resume()
694 if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) { in pir_resume()
695 KASSERT(!pci_link->pl_routed, in pir_resume()
696 ("link %#x is routed but has invalid PCI IRQ", in pir_resume()
697 pci_link->pl_id)); in pir_resume()
700 if (pci_link->pl_routed) { in pir_resume()
701 pd.bus = -1; in pir_resume()
702 pd.link = pci_link->pl_id; in pir_resume()
704 KASSERT(pd.bus != -1, in pir_resume()
706 pci_link->pl_id)); in pir_resume()
709 "Using %d.%d.INT%c to route link %#x to IRQ %d\n", in pir_resume()
710 pd.bus, pd.device, pd.pin + 'A', in pir_resume()
711 pci_link->pl_id, pci_link->pl_irq); in pir_resume()
712 error = pci_pir_biosroute(pd.bus, pd.device, 0, pd.pin, in pir_resume()
713 pci_link->pl_irq); in pir_resume()
717 pci_link->pl_id); in pir_resume()
724 /* Device interface */