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