Mon Aug 1 11:08:03 2011 UTC ()
add an experimental implementation of PCI MSIs (Message Signaled
Interrupts). Successfully tested with hdaudio and "wpi" wireless
ethernet.
notes:
-There seem to be buggy chips around which announce MSI support
 but don't correctly implement it. Thus the final word whether MSIs
 can be used should be by the driver.
-Only a single vector is supported. For multiple vectors, the IDT
 allocation code would have to be changed. (And we would possibly
 run into problems due to the limited number of vectors supported
 by the current code.)
-The code is "#if NIOAPIC > 0" because it uses the ioapic_edge
 interrupt stubs. These actually don't touch any ioapic, so this
 is somewhat a misnomer.
-MSIs can't be identified by a "pin" but only by a cpu/vector
 pair. Common intr code soesn't deal well with this yet.
-Drivers need to take care of saving/restoring MSI data in the device's
 config space on suspend/resume.


(drochner)
diff -r1.6 -r1.7 src/sys/arch/x86/include/pci_machdep_common.h
diff -r1.19 -r1.20 src/sys/arch/x86/pci/pci_intr_machdep.c

cvs diff -r1.6 -r1.7 src/sys/arch/x86/include/pci_machdep_common.h (switch to unified diff)

--- src/sys/arch/x86/include/pci_machdep_common.h 2011/04/04 20:37:55 1.6
+++ src/sys/arch/x86/include/pci_machdep_common.h 2011/08/01 11:08:03 1.7
@@ -1,142 +1,146 @@ @@ -1,142 +1,146 @@
1/* $NetBSD: pci_machdep_common.h,v 1.6 2011/04/04 20:37:55 dyoung Exp $ */ 1/* $NetBSD: pci_machdep_common.h,v 1.7 2011/08/01 11:08:03 drochner Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 4 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
5 * Copyright (c) 1994 Charles M. Hannum. All rights reserved. 5 * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 16 * must display the following acknowledgement:
17 * This product includes software developed by Charles M. Hannum. 17 * This product includes software developed by Charles M. Hannum.
18 * 4. The name of the author may not be used to endorse or promote products 18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission. 19 * derived from this software without specific prior written permission.
20 * 20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33#ifndef _X86_PCI_MACHDEP_COMMON_H_ 33#ifndef _X86_PCI_MACHDEP_COMMON_H_
34#define _X86_PCI_MACHDEP_COMMON_H_ 34#define _X86_PCI_MACHDEP_COMMON_H_
35 35
36/* 36/*
37 * Machine-specific definitions for PCI autoconfiguration. 37 * Machine-specific definitions for PCI autoconfiguration.
38 */ 38 */
39#define __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH 39#define __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH
40#ifndef XEN 40#ifndef XEN
41#define __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_DISESTABLISH 41#define __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_DISESTABLISH
42#endif 42#endif
43 43
44/* 44/*
45 * i386-specific PCI structure and type definitions. 45 * i386-specific PCI structure and type definitions.
46 * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. 46 * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
47 * 47 *
48 * Configuration tag; created from a {bus,device,function} triplet by 48 * Configuration tag; created from a {bus,device,function} triplet by
49 * pci_make_tag(), and passed to pci_conf_read() and pci_conf_write(). 49 * pci_make_tag(), and passed to pci_conf_read() and pci_conf_write().
50 * We could instead always pass the {bus,device,function} triplet to 50 * We could instead always pass the {bus,device,function} triplet to
51 * the read and write routines, but this would cause extra overhead. 51 * the read and write routines, but this would cause extra overhead.
52 * 52 *
53 * Mode 2 is historical and deprecated by the Revision 2.0 specification. 53 * Mode 2 is historical and deprecated by the Revision 2.0 specification.
54 */ 54 */
55union x86_pci_tag_u { 55union x86_pci_tag_u {
56 uint32_t mode1; 56 uint32_t mode1;
57 struct { 57 struct {
58 uint16_t port; 58 uint16_t port;
59 uint8_t enable; 59 uint8_t enable;
60 uint8_t forward; 60 uint8_t forward;
61 } mode2; 61 } mode2;
62}; 62};
63 63
64extern struct x86_bus_dma_tag pci_bus_dma_tag; 64extern struct x86_bus_dma_tag pci_bus_dma_tag;
65#ifdef _LP64 65#ifdef _LP64
66extern struct x86_bus_dma_tag pci_bus_dma64_tag; 66extern struct x86_bus_dma_tag pci_bus_dma64_tag;
67#endif 67#endif
68 68
69struct pci_attach_args; 69struct pci_attach_args;
70struct pci_chipset_tag; 70struct pci_chipset_tag;
71 71
72/* 72/*
73 * Types provided to machine-independent PCI code 73 * Types provided to machine-independent PCI code
74 */ 74 */
75typedef struct pci_chipset_tag *pci_chipset_tag_t; 75typedef struct pci_chipset_tag *pci_chipset_tag_t;
76typedef union x86_pci_tag_u pcitag_t; 76typedef union x86_pci_tag_u pcitag_t;
77 77
78struct pci_chipset_tag { 78struct pci_chipset_tag {
79 pci_chipset_tag_t pc_super; 79 pci_chipset_tag_t pc_super;
80 uint64_t pc_present; 80 uint64_t pc_present;
81 const struct pci_overrides *pc_ov; 81 const struct pci_overrides *pc_ov;
82 void *pc_ctx; 82 void *pc_ctx;
83}; 83};
84 84
85/* 85/*
86 * i386-specific PCI variables and functions. 86 * i386-specific PCI variables and functions.
87 * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE. 87 * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
88 */ 88 */
89int pci_bus_flags(void); 89int pci_bus_flags(void);
90int pci_mode_detect(void); 90int pci_mode_detect(void);
91void pci_mode_set(int); 91void pci_mode_set(int);
92 92
93/* 93/*
94 * Functions provided to machine-independent PCI code. 94 * Functions provided to machine-independent PCI code.
95 */ 95 */
96void pci_attach_hook(device_t, device_t, 96void pci_attach_hook(device_t, device_t,
97 struct pcibus_attach_args *); 97 struct pcibus_attach_args *);
98int pci_bus_maxdevs(pci_chipset_tag_t, int); 98int pci_bus_maxdevs(pci_chipset_tag_t, int);
99pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int); 99pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int);
100void pci_decompose_tag(pci_chipset_tag_t, pcitag_t, 100void pci_decompose_tag(pci_chipset_tag_t, pcitag_t,
101 int *, int *, int *); 101 int *, int *, int *);
102pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int); 102pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int);
103void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, 103void pci_conf_write(pci_chipset_tag_t, pcitag_t, int,
104 pcireg_t); 104 pcireg_t);
105int pci_intr_map(const struct pci_attach_args *, 105int pci_intr_map(const struct pci_attach_args *,
106 pci_intr_handle_t *); 106 pci_intr_handle_t *);
107const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t); 107const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t);
108const struct evcnt *pci_intr_evcnt(pci_chipset_tag_t, pci_intr_handle_t); 108const struct evcnt *pci_intr_evcnt(pci_chipset_tag_t, pci_intr_handle_t);
109void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t, 109void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
110 int, int (*)(void *), void *); 110 int, int (*)(void *), void *);
111void pci_intr_disestablish(pci_chipset_tag_t, void *); 111void pci_intr_disestablish(pci_chipset_tag_t, void *);
112 112
 113/* experimental MSI support */
 114void *pci_msi_establish(struct pci_attach_args *, int, int (*)(void *), void *);
 115void pci_msi_disestablish(void *);
 116
113/* 117/*
114 * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED 118 * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED
115 * BY PORTABLE CODE. 119 * BY PORTABLE CODE.
116 */ 120 */
117 121
118/* Extract Bus Number for a host bridge or -1 if unknown. */ 122/* Extract Bus Number for a host bridge or -1 if unknown. */
119int pchb_get_bus_number(pci_chipset_tag_t, pcitag_t); 123int pchb_get_bus_number(pci_chipset_tag_t, pcitag_t);
120 124
121/* 125/*
122 * Section 6.2.4, `Miscellaneous Functions' of the PCI Specification, 126 * Section 6.2.4, `Miscellaneous Functions' of the PCI Specification,
123 * says that 255 means `unknown' or `no connection' to the interrupt 127 * says that 255 means `unknown' or `no connection' to the interrupt
124 * controller on a PC. 128 * controller on a PC.
125 */ 129 */
126#define X86_PCI_INTERRUPT_LINE_NO_CONNECTION 0xff 130#define X86_PCI_INTERRUPT_LINE_NO_CONNECTION 0xff
127 131
128void pci_device_foreach(pci_chipset_tag_t, int, 132void pci_device_foreach(pci_chipset_tag_t, int,
129 void (*)(pci_chipset_tag_t, pcitag_t, void*), 133 void (*)(pci_chipset_tag_t, pcitag_t, void*),
130 void *); 134 void *);
131  135
132void pci_device_foreach_min(pci_chipset_tag_t, int, int, 136void pci_device_foreach_min(pci_chipset_tag_t, int, int,
133 void (*)(pci_chipset_tag_t, pcitag_t, void*), 137 void (*)(pci_chipset_tag_t, pcitag_t, void*),
134 void *); 138 void *);
135  139
136void pci_bridge_foreach(pci_chipset_tag_t, int, int, 140void pci_bridge_foreach(pci_chipset_tag_t, int, int,
137 void (*) (pci_chipset_tag_t, pcitag_t, void *), void *); 141 void (*) (pci_chipset_tag_t, pcitag_t, void *), void *);
138 142
139void pci_mmio_range_infer(pci_chipset_tag_t, int, int, bus_addr_t *, 143void pci_mmio_range_infer(pci_chipset_tag_t, int, int, bus_addr_t *,
140 bus_size_t *); 144 bus_size_t *);
141 145
142#endif /* _X86_PCI_MACHDEP_COMMON_H_ */ 146#endif /* _X86_PCI_MACHDEP_COMMON_H_ */

cvs diff -r1.19 -r1.20 src/sys/arch/x86/pci/pci_intr_machdep.c (switch to unified diff)

--- src/sys/arch/x86/pci/pci_intr_machdep.c 2011/04/04 20:37:55 1.19
+++ src/sys/arch/x86/pci/pci_intr_machdep.c 2011/08/01 11:08:03 1.20
@@ -1,327 +1,418 @@ @@ -1,327 +1,418 @@
1/* $NetBSD: pci_intr_machdep.c,v 1.19 2011/04/04 20:37:55 dyoung Exp $ */ 1/* $NetBSD: pci_intr_machdep.c,v 1.20 2011/08/01 11:08:03 drochner Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997, 1998, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997, 1998, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center. 9 * NASA Ames Research Center.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 34 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
35 * Copyright (c) 1994 Charles M. Hannum. All rights reserved. 35 * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
36 * 36 *
37 * Redistribution and use in source and binary forms, with or without 37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions 38 * modification, are permitted provided that the following conditions
39 * are met: 39 * are met:
40 * 1. Redistributions of source code must retain the above copyright 40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer. 41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright 42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the 43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution. 44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software 45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement: 46 * must display the following acknowledgement:
47 * This product includes software developed by Charles M. Hannum. 47 * This product includes software developed by Charles M. Hannum.
48 * 4. The name of the author may not be used to endorse or promote products 48 * 4. The name of the author may not be used to endorse or promote products
49 * derived from this software without specific prior written permission. 49 * derived from this software without specific prior written permission.
50 * 50 *
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
53 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 53 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
54 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 54 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
55 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 55 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
60 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 */ 61 */
62 62
63/* 63/*
64 * Machine-specific functions for PCI autoconfiguration. 64 * Machine-specific functions for PCI autoconfiguration.
65 * 65 *
66 * On PCs, there are two methods of generating PCI configuration cycles. 66 * On PCs, there are two methods of generating PCI configuration cycles.
67 * We try to detect the appropriate mechanism for this machine and set 67 * We try to detect the appropriate mechanism for this machine and set
68 * up a few function pointers to access the correct method directly. 68 * up a few function pointers to access the correct method directly.
69 * 69 *
70 * The configuration method can be hard-coded in the config file by 70 * The configuration method can be hard-coded in the config file by
71 * using `options PCI_CONF_MODE=N', where `N' is the configuration mode 71 * using `options PCI_CONF_MODE=N', where `N' is the configuration mode
72 * as defined section 3.6.4.1, `Generating Configuration Cycles'. 72 * as defined section 3.6.4.1, `Generating Configuration Cycles'.
73 */ 73 */
74 74
75#include <sys/cdefs.h> 75#include <sys/cdefs.h>
76__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.19 2011/04/04 20:37:55 dyoung Exp $"); 76__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.20 2011/08/01 11:08:03 drochner Exp $");
77 77
78#include <sys/types.h> 78#include <sys/types.h>
79#include <sys/param.h> 79#include <sys/param.h>
80#include <sys/time.h> 80#include <sys/time.h>
81#include <sys/systm.h> 81#include <sys/systm.h>
82#include <sys/errno.h> 82#include <sys/errno.h>
83#include <sys/device.h> 83#include <sys/device.h>
84#include <sys/intr.h> 84#include <sys/intr.h>
 85#include <sys/malloc.h>
85 86
86#include <dev/pci/pcivar.h> 87#include <dev/pci/pcivar.h>
87 88
88#include "ioapic.h" 89#include "ioapic.h"
89#include "eisa.h" 90#include "eisa.h"
90#include "acpica.h" 91#include "acpica.h"
91#include "opt_mpbios.h" 92#include "opt_mpbios.h"
92#include "opt_acpi.h" 93#include "opt_acpi.h"
93 94
94#if NIOAPIC > 0 || NACPICA > 0 95#if NIOAPIC > 0 || NACPICA > 0
95#include <machine/i82093var.h> 96#include <machine/i82093var.h>
96#include <machine/mpconfig.h> 97#include <machine/mpconfig.h>
97#include <machine/mpbiosvar.h> 98#include <machine/mpbiosvar.h>
98#include <machine/pic.h> 99#include <machine/pic.h>
99#endif 100#endif
100 101
101#ifdef MPBIOS 102#ifdef MPBIOS
102#include <machine/mpbiosvar.h> 103#include <machine/mpbiosvar.h>
103#endif 104#endif
104 105
105#if NACPICA > 0 106#if NACPICA > 0
106#include <machine/mpacpi.h> 107#include <machine/mpacpi.h>
107#endif 108#endif
108 109
109#define MPSAFE_MASK 0x80000000 110#define MPSAFE_MASK 0x80000000
110 111
111int 112int
112pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 113pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
113{ 114{
114 int pin = pa->pa_intrpin; 115 int pin = pa->pa_intrpin;
115 int line = pa->pa_intrline; 116 int line = pa->pa_intrline;
116 pci_chipset_tag_t pc; 117 pci_chipset_tag_t pc;
117#if NIOAPIC > 0 || NACPICA > 0 118#if NIOAPIC > 0 || NACPICA > 0
118 int rawpin = pa->pa_rawintrpin; 119 int rawpin = pa->pa_rawintrpin;
119 int bus, dev, func; 120 int bus, dev, func;
120#endif 121#endif
121 122
122 if ((pc = pa->pa_pc) != NULL) { 123 if ((pc = pa->pa_pc) != NULL) {
123 if ((pc->pc_present & PCI_OVERRIDE_INTR_MAP) != 0) 124 if ((pc->pc_present & PCI_OVERRIDE_INTR_MAP) != 0)
124 return (*pc->pc_ov->ov_intr_map)(pc->pc_ctx, pa, ihp); 125 return (*pc->pc_ov->ov_intr_map)(pc->pc_ctx, pa, ihp);
125 if (pc->pc_super != NULL) { 126 if (pc->pc_super != NULL) {
126 struct pci_attach_args paclone = *pa; 127 struct pci_attach_args paclone = *pa;
127 paclone.pa_pc = pc->pc_super; 128 paclone.pa_pc = pc->pc_super;
128 return pci_intr_map(&paclone, ihp); 129 return pci_intr_map(&paclone, ihp);
129 } 130 }
130 } 131 }
131 132
132 if (pin == 0) { 133 if (pin == 0) {
133 /* No IRQ used. */ 134 /* No IRQ used. */
134 goto bad; 135 goto bad;
135 } 136 }
136 137
137 *ihp = 0; 138 *ihp = 0;
138 139
139 if (pin > PCI_INTERRUPT_PIN_MAX) { 140 if (pin > PCI_INTERRUPT_PIN_MAX) {
140 aprint_normal("pci_intr_map: bad interrupt pin %d\n", pin); 141 aprint_normal("pci_intr_map: bad interrupt pin %d\n", pin);
141 goto bad; 142 goto bad;
142 } 143 }
143 144
144#if NIOAPIC > 0 || NACPICA > 0 145#if NIOAPIC > 0 || NACPICA > 0
145 pci_decompose_tag(pc, pa->pa_tag, &bus, &dev, &func); 146 pci_decompose_tag(pc, pa->pa_tag, &bus, &dev, &func);
146 if (mp_busses != NULL) { 147 if (mp_busses != NULL) {
147 if (intr_find_mpmapping(bus, (dev<<2)|(rawpin-1), ihp) == 0) { 148 if (intr_find_mpmapping(bus, (dev<<2)|(rawpin-1), ihp) == 0) {
148 if ((*ihp & 0xff) == 0) 149 if ((*ihp & 0xff) == 0)
149 *ihp |= line; 150 *ihp |= line;
150 return 0; 151 return 0;
151 } 152 }
152 /* 153 /*
153 * No explicit PCI mapping found. This is not fatal, 154 * No explicit PCI mapping found. This is not fatal,
154 * we'll try the ISA (or possibly EISA) mappings next. 155 * we'll try the ISA (or possibly EISA) mappings next.
155 */ 156 */
156 } 157 }
157#endif 158#endif
158 159
159 /* 160 /*
160 * Section 6.2.4, `Miscellaneous Functions', says that 255 means 161 * Section 6.2.4, `Miscellaneous Functions', says that 255 means
161 * `unknown' or `no connection' on a PC. We assume that a device with 162 * `unknown' or `no connection' on a PC. We assume that a device with
162 * `no connection' either doesn't have an interrupt (in which case the 163 * `no connection' either doesn't have an interrupt (in which case the
163 * pin number should be 0, and would have been noticed above), or 164 * pin number should be 0, and would have been noticed above), or
164 * wasn't configured by the BIOS (in which case we punt, since there's 165 * wasn't configured by the BIOS (in which case we punt, since there's
165 * no real way we can know how the interrupt lines are mapped in the 166 * no real way we can know how the interrupt lines are mapped in the
166 * hardware). 167 * hardware).
167 * 168 *
168 * XXX 169 * XXX
169 * Since IRQ 0 is only used by the clock, and we can't actually be sure 170 * Since IRQ 0 is only used by the clock, and we can't actually be sure
170 * that the BIOS did its job, we also recognize that as meaning that 171 * that the BIOS did its job, we also recognize that as meaning that
171 * the BIOS has not configured the device. 172 * the BIOS has not configured the device.
172 */ 173 */
173 if (line == 0 || line == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) { 174 if (line == 0 || line == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) {
174 aprint_normal("pci_intr_map: no mapping for pin %c (line=%02x)\n", 175 aprint_normal("pci_intr_map: no mapping for pin %c (line=%02x)\n",
175 '@' + pin, line); 176 '@' + pin, line);
176 goto bad; 177 goto bad;
177 } else { 178 } else {
178 if (line >= NUM_LEGACY_IRQS) { 179 if (line >= NUM_LEGACY_IRQS) {
179 aprint_normal("pci_intr_map: bad interrupt line %d\n", line); 180 aprint_normal("pci_intr_map: bad interrupt line %d\n", line);
180 goto bad; 181 goto bad;
181 } 182 }
182 if (line == 2) { 183 if (line == 2) {
183 aprint_normal("pci_intr_map: changed line 2 to line 9\n"); 184 aprint_normal("pci_intr_map: changed line 2 to line 9\n");
184 line = 9; 185 line = 9;
185 } 186 }
186 } 187 }
187#if NIOAPIC > 0 || NACPICA > 0 188#if NIOAPIC > 0 || NACPICA > 0
188 if (mp_busses != NULL) { 189 if (mp_busses != NULL) {
189 if (intr_find_mpmapping(mp_isa_bus, line, ihp) == 0) { 190 if (intr_find_mpmapping(mp_isa_bus, line, ihp) == 0) {
190 if ((*ihp & 0xff) == 0) 191 if ((*ihp & 0xff) == 0)
191 *ihp |= line; 192 *ihp |= line;
192 return 0; 193 return 0;
193 } 194 }
194#if NEISA > 0 195#if NEISA > 0
195 if (intr_find_mpmapping(mp_eisa_bus, line, ihp) == 0) { 196 if (intr_find_mpmapping(mp_eisa_bus, line, ihp) == 0) {
196 if ((*ihp & 0xff) == 0) 197 if ((*ihp & 0xff) == 0)
197 *ihp |= line; 198 *ihp |= line;
198 return 0; 199 return 0;
199 } 200 }
200#endif 201#endif
201 aprint_normal("pci_intr_map: bus %d dev %d func %d pin %d; line %d\n", 202 aprint_normal("pci_intr_map: bus %d dev %d func %d pin %d; line %d\n",
202 bus, dev, func, pin, line); 203 bus, dev, func, pin, line);
203 aprint_normal("pci_intr_map: no MP mapping found\n"); 204 aprint_normal("pci_intr_map: no MP mapping found\n");
204 } 205 }
205#endif 206#endif
206 207
207 *ihp = line; 208 *ihp = line;
208 return 0; 209 return 0;
209 210
210bad: 211bad:
211 *ihp = -1; 212 *ihp = -1;
212 return 1; 213 return 1;
213} 214}
214 215
215const char * 216const char *
216pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih) 217pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih)
217{ 218{
218 219
219 if (pc != NULL) { 220 if (pc != NULL) {
220 if ((pc->pc_present & PCI_OVERRIDE_INTR_STRING) != 0) 221 if ((pc->pc_present & PCI_OVERRIDE_INTR_STRING) != 0)
221 return (*pc->pc_ov->ov_intr_string)(pc->pc_ctx, pc, ih); 222 return (*pc->pc_ov->ov_intr_string)(pc->pc_ctx, pc, ih);
222 if (pc->pc_super != NULL) 223 if (pc->pc_super != NULL)
223 return pci_intr_string(pc->pc_super, ih); 224 return pci_intr_string(pc->pc_super, ih);
224 } 225 }
225 226
226 return intr_string(ih & ~MPSAFE_MASK); 227 return intr_string(ih & ~MPSAFE_MASK);
227} 228}
228 229
229 230
230const struct evcnt * 231const struct evcnt *
231pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih) 232pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
232{ 233{
233 234
234 if (pc != NULL) { 235 if (pc != NULL) {
235 if ((pc->pc_present & PCI_OVERRIDE_INTR_EVCNT) != 0) 236 if ((pc->pc_present & PCI_OVERRIDE_INTR_EVCNT) != 0)
236 return (*pc->pc_ov->ov_intr_evcnt)(pc->pc_ctx, pc, ih); 237 return (*pc->pc_ov->ov_intr_evcnt)(pc->pc_ctx, pc, ih);
237 if (pc->pc_super != NULL) 238 if (pc->pc_super != NULL)
238 return pci_intr_evcnt(pc->pc_super, ih); 239 return pci_intr_evcnt(pc->pc_super, ih);
239 } 240 }
240 241
241 /* XXX for now, no evcnt parent reported */ 242 /* XXX for now, no evcnt parent reported */
242 return NULL; 243 return NULL;
243} 244}
244 245
245int 246int
246pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih, 247pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih,
247 int attr, uint64_t data) 248 int attr, uint64_t data)
248{ 249{
249 250
250 switch (attr) { 251 switch (attr) {
251 case PCI_INTR_MPSAFE: 252 case PCI_INTR_MPSAFE:
252 if (data) { 253 if (data) {
253 *ih |= MPSAFE_MASK; 254 *ih |= MPSAFE_MASK;
254 } else { 255 } else {
255 *ih &= ~MPSAFE_MASK; 256 *ih &= ~MPSAFE_MASK;
256 } 257 }
257 /* XXX Set live if already mapped. */ 258 /* XXX Set live if already mapped. */
258 return 0; 259 return 0;
259 default: 260 default:
260 return ENODEV; 261 return ENODEV;
261 } 262 }
262} 263}
263 264
264void * 265void *
265pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, 266pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
266 int level, int (*func)(void *), void *arg) 267 int level, int (*func)(void *), void *arg)
267{ 268{
268 int pin, irq; 269 int pin, irq;
269 struct pic *pic; 270 struct pic *pic;
270#if NIOAPIC > 0 271#if NIOAPIC > 0
271 struct ioapic_softc *ioapic; 272 struct ioapic_softc *ioapic;
272#endif 273#endif
273 bool mpsafe; 274 bool mpsafe;
274 275
275 if (pc != NULL) { 276 if (pc != NULL) {
276 if ((pc->pc_present & PCI_OVERRIDE_INTR_ESTABLISH) != 0) { 277 if ((pc->pc_present & PCI_OVERRIDE_INTR_ESTABLISH) != 0) {
277 return (*pc->pc_ov->ov_intr_establish)(pc->pc_ctx, 278 return (*pc->pc_ov->ov_intr_establish)(pc->pc_ctx,
278 pc, ih, level, func, arg); 279 pc, ih, level, func, arg);
279 } 280 }
280 if (pc->pc_super != NULL) { 281 if (pc->pc_super != NULL) {
281 return pci_intr_establish(pc->pc_super, ih, level, func, 282 return pci_intr_establish(pc->pc_super, ih, level, func,
282 arg); 283 arg);
283 } 284 }
284 } 285 }
285 286
286 pic = &i8259_pic; 287 pic = &i8259_pic;
287 pin = irq = (ih & ~MPSAFE_MASK); 288 pin = irq = (ih & ~MPSAFE_MASK);
288 mpsafe = ((ih & MPSAFE_MASK) != 0); 289 mpsafe = ((ih & MPSAFE_MASK) != 0);
289 290
290#if NIOAPIC > 0 291#if NIOAPIC > 0
291 if (ih & APIC_INT_VIA_APIC) { 292 if (ih & APIC_INT_VIA_APIC) {
292 ioapic = ioapic_find(APIC_IRQ_APIC(ih)); 293 ioapic = ioapic_find(APIC_IRQ_APIC(ih));
293 if (ioapic == NULL) { 294 if (ioapic == NULL) {
294 aprint_normal("pci_intr_establish: bad ioapic %d\n", 295 aprint_normal("pci_intr_establish: bad ioapic %d\n",
295 APIC_IRQ_APIC(ih)); 296 APIC_IRQ_APIC(ih));
296 return NULL; 297 return NULL;
297 } 298 }
298 pic = &ioapic->sc_pic; 299 pic = &ioapic->sc_pic;
299 pin = APIC_IRQ_PIN(ih); 300 pin = APIC_IRQ_PIN(ih);
300 irq = APIC_IRQ_LEGACY_IRQ(ih); 301 irq = APIC_IRQ_LEGACY_IRQ(ih);
301 if (irq < 0 || irq >= NUM_LEGACY_IRQS) 302 if (irq < 0 || irq >= NUM_LEGACY_IRQS)
302 irq = -1; 303 irq = -1;
303 } 304 }
304#endif 305#endif
305 306
306 return intr_establish(irq, pic, pin, IST_LEVEL, level, func, arg, 307 return intr_establish(irq, pic, pin, IST_LEVEL, level, func, arg,
307 mpsafe); 308 mpsafe);
308} 309}
309 310
310void 311void
311pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie) 312pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
312{ 313{
313 314
314 if (pc != NULL) { 315 if (pc != NULL) {
315 if ((pc->pc_present & PCI_OVERRIDE_INTR_ESTABLISH) != 0) { 316 if ((pc->pc_present & PCI_OVERRIDE_INTR_ESTABLISH) != 0) {
316 (*pc->pc_ov->ov_intr_disestablish)(pc->pc_ctx, 317 (*pc->pc_ov->ov_intr_disestablish)(pc->pc_ctx,
317 pc, cookie); 318 pc, cookie);
318 return; 319 return;
319 } 320 }
320 if (pc->pc_super != NULL) { 321 if (pc->pc_super != NULL) {
321 pci_intr_disestablish(pc->pc_super, cookie); 322 pci_intr_disestablish(pc->pc_super, cookie);
322 return; 323 return;
323 } 324 }
324 } 325 }
325 326
326 intr_disestablish(cookie); 327 intr_disestablish(cookie);
327} 328}
 329
 330#if NIOAPIC > 0
 331/*
 332 * experimental support for MSI, does support a single vector,
 333 * no MSI-X, 8-bit APIC IDs
 334 * (while it doesn't need the ioapic technically, it borrows
 335 * from its kernel support)
 336 */
 337
 338/* dummies, needed by common intr_establish code */
 339static void
 340msipic_hwmask(struct pic *pic, int pin)
 341{
 342}
 343static void
 344msipic_addroute(struct pic *pic, struct cpu_info *ci,
 345 int pin, int vec, int type)
 346{
 347}
 348
 349static struct pic msi_pic = {
 350 .pic_name = "msi",
 351 .pic_type = PIC_SOFT,
 352 .pic_vecbase = 0,
 353 .pic_apicid = 0,
 354 .pic_lock = __SIMPLELOCK_UNLOCKED,
 355 .pic_hwmask = msipic_hwmask,
 356 .pic_hwunmask = msipic_hwmask,
 357 .pic_addroute = msipic_addroute,
 358 .pic_delroute = msipic_addroute,
 359 .pic_edge_stubs = ioapic_edge_stubs,
 360};
 361
 362struct msi_hdl {
 363 struct intrhand *ih;
 364 pci_chipset_tag_t pc;
 365 pcitag_t tag;
 366 int co;
 367};
 368
 369void *
 370pci_msi_establish(struct pci_attach_args *pa, int level,
 371 int (*func)(void *), void *arg)
 372{
 373 int co;
 374 void *ih;
 375 struct msi_hdl *msih;
 376 struct cpu_info *ci;
 377 struct intrsource *s;
 378 u_int32_t cr;
 379
 380 if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI, &co, 0))
 381 return NULL;
 382
 383 ih = intr_establish(-1, &msi_pic, -1, IST_EDGE, level,
 384 func, arg, 0);
 385 if (!ih)
 386 return NULL;
 387
 388 msih = malloc(sizeof(*msih), M_DEVBUF, M_WAITOK);
 389 msih->ih = ih;
 390 msih->pc = pa->pa_pc;
 391 msih->tag = pa->pa_tag;
 392 msih->co = co;
 393
 394 ci = msih->ih->ih_cpu;
 395 s = ci->ci_isources[msih->ih->ih_slot];
 396 cr = pci_conf_read(pa->pa_pc, pa->pa_tag, co);
 397 pci_conf_write(pa->pa_pc, pa->pa_tag, co + 4,
 398 0xfee00000 | ci->ci_cpuid << 12);
 399 if (cr & 0x800000) {
 400 pci_conf_write(pa->pa_pc, pa->pa_tag, co + 8, 0);
 401 pci_conf_write(pa->pa_pc, pa->pa_tag, co + 12,
 402 s->is_idtvec | 0x4000);
 403 } else
 404 pci_conf_write(pa->pa_pc, pa->pa_tag, co + 8,
 405 s->is_idtvec | 0x4000);
 406 pci_conf_write(pa->pa_pc, pa->pa_tag, co, 0x10000);
 407 return ih;
 408}
 409
 410void
 411pci_msi_disestablish(void *ih)
 412{
 413 struct msi_hdl *msih = ih;
 414
 415 pci_conf_write(msih->pc, msih->tag, msih->co, 0);
 416 intr_disestablish(msih->ih);
 417}
 418#endif