1.\" $OpenBSD: pci_intr_map.9,v 1.19 2024/11/13 10:56:18 jsg Exp $ 2.\" 3.\" Copyright (c) 2005 Michael Shalayeff 4.\" All rights reserved. 5.\" 6.\" Permission to use, copy, modify, and distribute this software for any 7.\" purpose with or without fee is hereby granted, provided that the above 8.\" copyright notice and this permission notice appear in all copies. 9.\" 10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17.\" 18.Dd $Mdocdate: November 13 2024 $ 19.Dt PCI_INTR_MAP 9 20.Os 21.Sh NAME 22.Nm pci_intr_map , 23.Nm pci_intr_map_msi , 24.Nm pci_intr_map_msix , 25.Nm pci_intr_line , 26.Nm pci_intr_string , 27.Nm pci_intr_establish , 28.\" .Nm pci_intr_establish_cpu , 29.Nm pci_intr_disestablish 30.Nd PCI interrupts 31.Sh SYNOPSIS 32.In alpha/pci/pci_machdep.h 33.In i386/pci/pci_machdep.h 34.In machine/pci_machdep.h 35.Ft int 36.Fn pci_intr_map "struct pci_attach_args *paa" "pci_intr_handle_t *ih" 37.Ft int 38.Fn pci_intr_map_msi "struct pci_attach_args *paa" "pci_intr_handle_t *ih" 39.Ft int 40.Fo pci_intr_map_msix 41.Fa "struct pci_attach_args *paa" 42.Fa "int vector" 43.Fa "pci_intr_handle_t *ih" 44.Fc 45.Ft int 46.Fn pci_intr_line "pci_intr_handle_t ih" 47.Ft const char * 48.Fn pci_intr_string "pci_chipset_tag_t pc" "pci_intr_handle_t ih" 49.Ft void * 50.Fo pci_intr_establish 51.Fa "pci_chipset_tag_t pc" 52.Fa "pci_intr_handle_t ih" 53.Fa "int level" 54.Fa "int (*func)(void *)" 55.Fa "void *arg" 56.Fa "const char *name" 57.Fc 58.\" .Ft void * 59.\" .Fo pci_intr_establish_cpu 60.\" .Fa "pci_chipset_tag_t pc" 61.\" .Fa "pci_intr_handle_t ih" 62.\" .Fa "int level" 63.\" .Fa "struct cpu_info *ci" 64.\" .Fa "int (*func)(void *)" 65.\" .Fa "void *arg" 66.\" .Fa "const char *name" 67.\" .Fc 68.Ft void 69.Fn pci_intr_disestablish "pci_chipset_tag_t pc" "void *v" 70.Sh DESCRIPTION 71These functions are provided by the machine-dependent implementation 72for attaching handler functions to the interrupts of PCI devices. 73.Pp 74An architect type is provided by the machine-dependent 75code 76.Va pci_intr_handle_t , 77to be initialised by 78.Fn pci_intr_map , 79.Fn pci_intr_map_msi , 80or 81.Fn pci_intr_map_msix . 82.Pp 83The 84.Fn pci_intr_map 85function should be called first to establish a mapping between a PCI 86pin and the interrupt controller's interrupt vector. 87This process may include resolving the mapping through 88firmware-provided information. 89.Pp 90For devices that support Message Signaled Interrupts (MSI) the 91.Fn pci_intr_map_msi 92function should be called instead. 93This function can fail if the 94system does not support MSI. 95In that case 96.Fn pci_intr_map 97should be called to fall back on classic PCI interrupts. 98.Pp 99For devices that support Extended Message Signaled Interrupts (MSI-X) the 100.Fn pci_intr_map_msix 101function can be called instead. 102This function can fail if the system does not support MSI-X. 103In that case 104.Fn pci_intr_map_msi 105or 106.Fn pci_intr_map 107can be called to fall back on Message Signalled Interrupts or classic 108PCI interrupts respectively. 109MSI-X can provide multiple interrupt vectors per device. 110For each vector, a separate call to 111.Fn pci_intr_map_msix 112is made with the 113.Fa vector 114argument specifying which interrupt vector to map. 115.Pp 116Having initialised the 117.Fa pci_intr_handle_t 118in the previous step, an interrupt handler can be established using 119.Fn pci_intr_establish . 120.\" or 121.\" .Fn pci_intr_establish_cpu . 122.\" .Fn pci_intr_establish_cpu 123.\" establishes an interrupt on the CPU specified in the 124.\" .Fa ci 125.\" argument, while 126.\" .Fn pci_intr_establish 127.\" uses a system selected CPU. 128An established interrupt handler is always called with the system 129interrupt priority level set equal to, or higher than, 130.Fa level . 131.Pp 132A printable string representation of an initialised interrupt mapping 133can be generated with 134.Fn pci_intr_string . 135.Pp 136.Fn pci_intr_line 137provides the interrupt line extracted from the MD interrupt handle. 138Upon device detachment, 139.Fn pci_intr_disestablish 140should be used to disassociate the handler from the interrupt. 141.Pp 142See 143.Xr spl 9 144for an explanation of the 145.Va ipl 146.Dq interrupt priority levels . 147.Sh EXAMPLES 148A typical code sequence for establishing a handler 149for a device interrupt in the driver might be: 150.Bd -literal -offset 3n 151int 152xxxattach(struct device *parent, struct device *self, void *aux) 153{ 154 struct xxx_softc *sc = (struct xxx_softc *)self; 155 struct pci_attach_args *pa = aux; 156 pci_intr_handle_t ih; 157 const char *intrstr; 158 bus_size_t size; 159 160 \&... 161 162 if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) { 163 printf(": can't map interrupt\en"); 164 bus_space_unmap(sc->iot, sc->ioh, size); 165 return; 166 } 167 intrstr = pci_intr_string(pa->pa_pc, ih); 168 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, 169 xxx_intr, sc, sc->sc_dev.dv_xname); 170 if (!sc->sc_ih) { 171 printf(": can't establish interrupt"); 172 if (intrstr) 173 printf(" at %s", intrstr); 174 printf("\en"); 175 bus_space_unmap(sc->iot, sc->ioh, size); 176 return; 177 } 178 179 printf(": %s\en", intrstr); 180 181 \&... 182} 183.Ed 184.Sh SEE ALSO 185.Xr cardbus 4 , 186.Xr pci 4 , 187.Xr pcibios 4 , 188.Xr pci_conf_read 9 , 189.Xr spl 9 190.Sh HISTORY 191These functions first appeared in 192.Ox 1.2 . 193.\" .Sh AUTHORS 194