]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/x86/pci/pci_early_quirks.c
Upgrade to OpenSSH 7.9p1.
[FreeBSD/FreeBSD.git] / sys / x86 / pci / pci_early_quirks.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Johannes Lundberg
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/kernel.h>
35 #include <vm/vm.h>
36 /* XXX: enable this once the KPI is available */
37 /* #include <x86/physmem.h> */
38 #include <machine/pci_cfgreg.h>
39 #include <machine/md_var.h>
40 #include <dev/pci/pcivar.h>
41 #include <dev/pci/pcireg.h>
42
43 #include <x86/pci/pci_early_quirks.h>
44
45 #define MiB(v) ((unsigned long)(v) << 20)
46
47 struct pci_device_id {
48         uint32_t        vendor;
49         uint32_t        device;
50         const struct intel_stolen_ops *data;
51 };
52
53 /*
54  * These global variables are read by LinuxKPI.
55  * LinuxKPI provide this information to the i915 driver.
56  */
57 vm_paddr_t intel_graphics_stolen_base = 0;
58 vm_paddr_t intel_graphics_stolen_size = 0;
59
60 /*
61  * Intel early quirks functions
62  */
63 static vm_paddr_t
64 intel_stolen_base_gen3(int bus, int slot, int func)
65 {
66         uint32_t ctrl;
67         vm_paddr_t val;
68
69         ctrl = pci_cfgregread(bus, slot, func, INTEL_BSM, 4);
70         val = ctrl & INTEL_BSM_MASK;
71         return (val);
72 }
73
74 static vm_paddr_t
75 intel_stolen_size_gen3(int bus, int slot, int func)
76 {
77         uint32_t ctrl;
78         vm_paddr_t val;
79
80         ctrl = pci_cfgregread(0, 0, 0, I830_GMCH_CTRL, 2);
81         val = ctrl & I855_GMCH_GMS_MASK;
82
83         switch (val) {
84         case I855_GMCH_GMS_STOLEN_1M:
85                 return (MiB(1));
86         case I855_GMCH_GMS_STOLEN_4M:
87                 return (MiB(4));
88         case I855_GMCH_GMS_STOLEN_8M:
89                 return (MiB(8));
90         case I855_GMCH_GMS_STOLEN_16M:
91                 return (MiB(16));
92         case I855_GMCH_GMS_STOLEN_32M:
93                 return (MiB(32));
94         case I915_GMCH_GMS_STOLEN_48M:
95                 return (MiB(48));
96         case I915_GMCH_GMS_STOLEN_64M:
97                 return (MiB(64));
98         case G33_GMCH_GMS_STOLEN_128M:
99                 return (MiB(128));
100         case G33_GMCH_GMS_STOLEN_256M:
101                 return (MiB(256));
102         case INTEL_GMCH_GMS_STOLEN_96M:
103                 return (MiB(96));
104         case INTEL_GMCH_GMS_STOLEN_160M:
105                 return (MiB(160));
106         case INTEL_GMCH_GMS_STOLEN_224M:
107                 return (MiB(224));
108         case INTEL_GMCH_GMS_STOLEN_352M:
109                 return (MiB(352));
110         }
111         return (0);
112 }
113
114 static vm_paddr_t
115 intel_stolen_size_gen6(int bus, int slot, int func)
116 {
117         uint32_t ctrl;
118         vm_paddr_t val;
119
120         ctrl = pci_cfgregread(bus, slot, func, SNB_GMCH_CTRL, 2);
121         val = (ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
122         return (val * MiB(32));
123 }
124
125 static vm_paddr_t
126 intel_stolen_size_gen8(int bus, int slot, int func)
127 {
128         uint32_t ctrl;
129         vm_paddr_t val;
130
131         ctrl = pci_cfgregread(bus, slot, func, SNB_GMCH_CTRL, 2);
132         val = (ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
133         return (val * MiB(32));
134 }
135
136 static vm_paddr_t
137 intel_stolen_size_chv(int bus, int slot, int func)
138 {
139         uint32_t ctrl;
140         vm_paddr_t val;
141
142         ctrl = pci_cfgregread(bus, slot, func, SNB_GMCH_CTRL, 2);
143         val = (ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
144
145         /*
146          * 0x0  to 0x10: 32MB increments starting at 0MB
147          * 0x11 to 0x16: 4MB increments starting at 8MB
148          * 0x17 to 0x1d: 4MB increments start at 36MB
149          */
150         if (val < 0x11)
151                 return (val * MiB(32));
152         else if (val < 0x17)
153                 return ((val - 0x11) * MiB(4) + MiB(8));
154         else
155                 return ((val - 0x17) * MiB(4) + MiB(36));
156 }
157
158 static vm_paddr_t
159 intel_stolen_size_gen9(int bus, int slot, int func)
160 {
161         uint32_t ctrl;
162         vm_paddr_t val;
163
164         ctrl = pci_cfgregread(bus, slot, func, SNB_GMCH_CTRL, 2);
165         val = (ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
166
167         /* 0x0  to 0xEF: 32MB increments starting at 0MB */
168         /* 0xF0 to 0xFE: 4MB increments starting at 4MB */
169         if (val < 0xF0)
170                 return (val * MiB(32));
171         return ((val - 0xF0) * MiB(4) + MiB(4));
172 }
173
174 struct intel_stolen_ops {
175         vm_paddr_t (*base)(int bus, int slot, int func);
176         vm_paddr_t (*size)(int bus, int slot, int func);
177 };
178
179 static const struct intel_stolen_ops intel_stolen_ops_gen3 = {
180         .base = intel_stolen_base_gen3,
181         .size = intel_stolen_size_gen3,
182 };
183
184 static const struct intel_stolen_ops intel_stolen_ops_gen6 = {
185         .base = intel_stolen_base_gen3,
186         .size = intel_stolen_size_gen6,
187 };
188
189 static const struct intel_stolen_ops intel_stolen_ops_gen8 = {
190         .base = intel_stolen_base_gen3,
191         .size = intel_stolen_size_gen8,
192 };
193
194 static const struct intel_stolen_ops intel_stolen_ops_gen9 = {
195         .base = intel_stolen_base_gen3,
196         .size = intel_stolen_size_gen9,
197 };
198
199 static const struct intel_stolen_ops intel_stolen_ops_chv = {
200         .base = intel_stolen_base_gen3,
201         .size = intel_stolen_size_chv,
202 };
203
204 static const struct pci_device_id intel_ids[] = {
205         INTEL_I915G_IDS(&intel_stolen_ops_gen3),
206         INTEL_I915GM_IDS(&intel_stolen_ops_gen3),
207         INTEL_I945G_IDS(&intel_stolen_ops_gen3),
208         INTEL_I945GM_IDS(&intel_stolen_ops_gen3),
209         INTEL_VLV_IDS(&intel_stolen_ops_gen6),
210         INTEL_PINEVIEW_IDS(&intel_stolen_ops_gen3),
211         INTEL_I965G_IDS(&intel_stolen_ops_gen3),
212         INTEL_G33_IDS(&intel_stolen_ops_gen3),
213         INTEL_I965GM_IDS(&intel_stolen_ops_gen3),
214         INTEL_GM45_IDS(&intel_stolen_ops_gen3),
215         INTEL_G45_IDS(&intel_stolen_ops_gen3),
216         INTEL_IRONLAKE_D_IDS(&intel_stolen_ops_gen3),
217         INTEL_IRONLAKE_M_IDS(&intel_stolen_ops_gen3),
218         INTEL_SNB_D_IDS(&intel_stolen_ops_gen6),
219         INTEL_SNB_M_IDS(&intel_stolen_ops_gen6),
220         INTEL_IVB_M_IDS(&intel_stolen_ops_gen6),
221         INTEL_IVB_D_IDS(&intel_stolen_ops_gen6),
222         INTEL_HSW_IDS(&intel_stolen_ops_gen6),
223         INTEL_BDW_IDS(&intel_stolen_ops_gen8),
224         INTEL_CHV_IDS(&intel_stolen_ops_chv),
225         INTEL_SKL_IDS(&intel_stolen_ops_gen9),
226         INTEL_BXT_IDS(&intel_stolen_ops_gen9),
227         INTEL_KBL_IDS(&intel_stolen_ops_gen9),
228         INTEL_CFL_IDS(&intel_stolen_ops_gen9),
229         INTEL_GLK_IDS(&intel_stolen_ops_gen9),
230         INTEL_CNL_IDS(&intel_stolen_ops_gen9),
231 };
232
233 /*
234  * Buggy BIOS don't reserve memory for the GPU properly and the OS
235  * can claim it before the GPU driver is loaded. This function will
236  * check the registers for base and size of this memory and reserve
237  * it for the GPU driver.
238  * gen3 (2004) and newer devices are supported. Support for older hw
239  * can be ported from Linux if needed.
240  */
241 static void
242 intel_graphics_stolen(void)
243 {
244         const struct intel_stolen_ops *ops;
245         uint32_t vendor, device, class;
246         int i;
247
248         /* XXX: Scan bus instead of assuming 0:2:0? */
249         const int bus = 0;
250         const int slot = 2;
251         const int func = 0;
252
253         if (pci_cfgregopen() == 0)
254                 return;
255
256         vendor = pci_cfgregread(bus, slot, func, PCIR_VENDOR, 2);
257         if (vendor != PCI_VENDOR_INTEL)
258                 return;
259
260         class = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 2);
261         if (class != PCI_CLASS_VGA)
262                 return;
263
264         device = pci_cfgregread(bus, slot, func, PCIR_DEVICE, 2);
265         if (device == 0xFFFF)
266                 return;
267
268         for (i = 0; i < nitems(intel_ids); i++) {
269                 if (intel_ids[i].device != device)
270                         continue;
271                 ops = intel_ids[i].data;
272                 intel_graphics_stolen_base = ops->base(bus, slot, func);
273                 intel_graphics_stolen_size = ops->size(bus, slot, func);
274                 break;
275         }
276
277         /* XXX: enable this once the KPI is available */
278         /* phys_avail_reserve(intel_graphics_stolen_base, */
279         /*     intel_graphics_stolen_base + intel_graphics_stolen_size); */
280 }
281
282 void
283 pci_early_quirks(void)
284 {
285
286         intel_graphics_stolen();
287 }