xref: /openbsd-src/share/man/man9/pci_intr_map.9 (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
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