2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2018 Johannes Lundberg
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
32 #include <sys/systm.h>
34 #include <sys/kernel.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>
43 #include <x86/pci/pci_early_quirks.h>
45 #define MiB(v) ((unsigned long)(v) << 20)
47 struct pci_device_id {
50 const struct intel_stolen_ops *data;
54 * These global variables are read by LinuxKPI.
55 * LinuxKPI provide this information to the i915 driver.
57 vm_paddr_t intel_graphics_stolen_base = 0;
58 vm_paddr_t intel_graphics_stolen_size = 0;
61 * Intel early quirks functions
64 intel_stolen_base_gen3(int bus, int slot, int func)
69 ctrl = pci_cfgregread(bus, slot, func, INTEL_BSM, 4);
70 val = ctrl & INTEL_BSM_MASK;
75 intel_stolen_size_gen3(int bus, int slot, int func)
80 ctrl = pci_cfgregread(0, 0, 0, I830_GMCH_CTRL, 2);
81 val = ctrl & I855_GMCH_GMS_MASK;
84 case I855_GMCH_GMS_STOLEN_1M:
86 case I855_GMCH_GMS_STOLEN_4M:
88 case I855_GMCH_GMS_STOLEN_8M:
90 case I855_GMCH_GMS_STOLEN_16M:
92 case I855_GMCH_GMS_STOLEN_32M:
94 case I915_GMCH_GMS_STOLEN_48M:
96 case I915_GMCH_GMS_STOLEN_64M:
98 case G33_GMCH_GMS_STOLEN_128M:
100 case G33_GMCH_GMS_STOLEN_256M:
102 case INTEL_GMCH_GMS_STOLEN_96M:
104 case INTEL_GMCH_GMS_STOLEN_160M:
106 case INTEL_GMCH_GMS_STOLEN_224M:
108 case INTEL_GMCH_GMS_STOLEN_352M:
115 intel_stolen_size_gen6(int bus, int slot, int func)
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));
126 intel_stolen_size_gen8(int bus, int slot, int func)
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));
137 intel_stolen_size_chv(int bus, int slot, int func)
142 ctrl = pci_cfgregread(bus, slot, func, SNB_GMCH_CTRL, 2);
143 val = (ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
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
151 return (val * MiB(32));
153 return ((val - 0x11) * MiB(4) + MiB(8));
155 return ((val - 0x17) * MiB(4) + MiB(36));
159 intel_stolen_size_gen9(int bus, int slot, int func)
164 ctrl = pci_cfgregread(bus, slot, func, SNB_GMCH_CTRL, 2);
165 val = (ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
167 /* 0x0 to 0xEF: 32MB increments starting at 0MB */
168 /* 0xF0 to 0xFE: 4MB increments starting at 4MB */
170 return (val * MiB(32));
171 return ((val - 0xF0) * MiB(4) + MiB(4));
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);
179 static const struct intel_stolen_ops intel_stolen_ops_gen3 = {
180 .base = intel_stolen_base_gen3,
181 .size = intel_stolen_size_gen3,
184 static const struct intel_stolen_ops intel_stolen_ops_gen6 = {
185 .base = intel_stolen_base_gen3,
186 .size = intel_stolen_size_gen6,
189 static const struct intel_stolen_ops intel_stolen_ops_gen8 = {
190 .base = intel_stolen_base_gen3,
191 .size = intel_stolen_size_gen8,
194 static const struct intel_stolen_ops intel_stolen_ops_gen9 = {
195 .base = intel_stolen_base_gen3,
196 .size = intel_stolen_size_gen9,
199 static const struct intel_stolen_ops intel_stolen_ops_chv = {
200 .base = intel_stolen_base_gen3,
201 .size = intel_stolen_size_chv,
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),
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.
242 intel_graphics_stolen(void)
244 const struct intel_stolen_ops *ops;
245 uint32_t vendor, device, class;
248 /* XXX: Scan bus instead of assuming 0:2:0? */
253 if (pci_cfgregopen() == 0)
256 vendor = pci_cfgregread(bus, slot, func, PCIR_VENDOR, 2);
257 if (vendor != PCI_VENDOR_INTEL)
260 class = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 2);
261 if (class != PCI_CLASS_VGA)
264 device = pci_cfgregread(bus, slot, func, PCIR_DEVICE, 2);
265 if (device == 0xFFFF)
268 for (i = 0; i < nitems(intel_ids); i++) {
269 if (intel_ids[i].device != device)
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);
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); */
283 pci_early_quirks(void)
286 intel_graphics_stolen();