1.\" $OpenBSD: pci_intr_map.9,v 1.17 2020/06/17 08:20:42 dlg 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: June 17 2020 $ 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 powerpc/pci/pci_machdep.h 35.In sgi/pci/pci_machdep.h 36.In machine/pci_machdep.h 37.Ft int 38.Fn pci_intr_map "struct pci_attach_args *paa" "pci_intr_handle_t *ih" 39.Ft int 40.Fn pci_intr_map_msi "struct pci_attach_args *paa" "pci_intr_handle_t *ih" 41.Ft int 42.Fo pci_intr_map_msix 43.Fa "struct pci_attach_args *paa" 44.Fa "int vector" 45.Fa "pci_intr_handle_t *ih" 46.Fc 47.Ft int 48.Fn pci_intr_line "pci_intr_handle_t ih" 49.Ft const char * 50.Fn pci_intr_string "pci_chipset_tag_t pc" "pci_intr_handle_t ih" 51.Ft void * 52.Fo pci_intr_establish 53.Fa "pci_chipset_tag_t pc" 54.Fa "pci_intr_handle_t ih" 55.Fa "int level" 56.Fa "int (*func)(void *)" 57.Fa "void *arg" 58.Fa "const char *name" 59.Fc 60.\" .Ft void * 61.\" .Fo pci_intr_establish_cpu 62.\" .Fa "pci_chipset_tag_t pc" 63.\" .Fa "pci_intr_handle_t ih" 64.\" .Fa "int level" 65.\" .Fa "struct cpu_info *ci" 66.\" .Fa "int (*func)(void *)" 67.\" .Fa "void *arg" 68.\" .Fa "const char *name" 69.\" .Fc 70.Ft void 71.Fn pci_intr_disestablish "pci_chipset_tag_t pc" "void *v" 72.Sh DESCRIPTION 73These functions are provided by the machine-dependent implementation 74for attaching handler functions to the interrupts of PCI devices. 75.Pp 76An architect type is provided by the machine-dependent 77code 78.Va pci_intr_handle_t , 79to be initialised by 80.Fn pci_intr_map , 81.Fn pci_intr_map_msi , 82or 83.Fn pci_intr_map_msix . 84.Pp 85The 86.Fn pci_intr_map 87function should be called first to establish a mapping between a PCI 88pin and the interrupt controller's interrupt vector. 89This process may include resolving the mapping through 90firmware-provided information. 91.Pp 92For devices that support Message Signaled Interrupts (MSI) the 93.Fn pci_intr_map_msi 94function should be called instead. 95This function can fail if the 96system does not support MSI. 97In that case 98.Fn pci_intr_map 99should be called to fall back on classic PCI interrupts. 100.Pp 101For devices that support Extended Message Signaled Interrupts (MSI-X) the 102.Fn pci_intr_map_msix 103function can be called instead. 104This function can fail if the system does not support MSI-X. 105In that case 106.Fn pci_intr_map_msi 107or 108.Fn pci_intr_map 109can be called to fall back on Message Signalled Interrupts or classic 110PCI interrupts respectively. 111MSI-X can provide multiple interrupt vectors per device. 112For each vector, a separate call to 113.Fn pci_intr_map_msix 114is made with the 115.Fa vector 116argument specifying which interrupt vector to map. 117.Pp 118Having initialised the 119.Fa pci_intr_handle_t 120in the previous step, an interrupt handler can be established using 121.Fn pci_intr_establish . 122.\" or 123.\" .Fn pci_intr_establish_cpu . 124.\" .Fn pci_intr_establish_cpu 125.\" establishes an interrupt on the CPU specified in the 126.\" .Fa ci 127.\" argument, while 128.\" .Fn pci_intr_establish 129.\" uses a system selected CPU. 130An established interrupt handler is always called with the system 131interrupt priority level set equal to, or higher than, 132.Fa level . 133.Pp 134A printable string representation of an initialised interrupt mapping 135can be generated with 136.Fn pci_intr_string . 137.Pp 138.Fn pci_intr_line 139provides the interrupt line extracted from the MD interrupt handle. 140Upon device detachment, 141.Fn pci_intr_disestablish 142should be used to disassociate the handler from the interrupt. 143.Pp 144See 145.Xr spl 9 146for an explanation of the 147.Va ipl 148.Dq interrupt priority levels . 149.Sh EXAMPLES 150A typical code sequence for establishing a handler 151for a device interrupt in the driver might be: 152.Bd -literal -offset 3n 153int 154xxxattach(struct device *parent, struct device *self, void *aux) 155{ 156 struct xxx_softc *sc = (struct xxx_softc *)self; 157 struct pci_attach_args *pa = aux; 158 pci_intr_handle_t ih; 159 const char *intrstr; 160 bus_size_t size; 161 162 \&... 163 164 if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) { 165 printf(": can't map interrupt\en"); 166 bus_space_unmap(sc->iot, sc->ioh, size); 167 return; 168 } 169 intrstr = pci_intr_string(pa->pa_pc, ih); 170 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, 171 xxx_intr, sc, sc->sc_dev.dv_xname); 172 if (!sc->sc_ih) { 173 printf(": can't establish interrupt"); 174 if (intrstr) 175 printf(" at %s", intrstr); 176 printf("\en"); 177 bus_space_unmap(sc->iot, sc->ioh, size); 178 return; 179 } 180 181 printf(": %s\en", intrstr); 182 183 \&... 184} 185.Ed 186.Sh SEE ALSO 187.Xr cardbus 4 , 188.Xr pci 4 , 189.Xr pcibios 4 , 190.Xr pci_conf_read 9 , 191.Xr spl 9 192.Sh HISTORY 193These functions first appeared in 194.Ox 1.2 . 195.\" .Sh AUTHORS 196