1*f41a5bb1Sriastradh /* $NetBSD: intel_gtt_subr.c,v 1.3 2021/12/19 12:37:36 riastradh Exp $ */
20c301abaSriastradh
30c301abaSriastradh /*-
40c301abaSriastradh * Copyright (c) 2014 The NetBSD Foundation, Inc.
50c301abaSriastradh * All rights reserved.
60c301abaSriastradh *
70c301abaSriastradh * This code is derived from software contributed to The NetBSD Foundation
80c301abaSriastradh * by Taylor R. Campbell.
90c301abaSriastradh *
100c301abaSriastradh * Redistribution and use in source and binary forms, with or without
110c301abaSriastradh * modification, are permitted provided that the following conditions
120c301abaSriastradh * are met:
130c301abaSriastradh * 1. Redistributions of source code must retain the above copyright
140c301abaSriastradh * notice, this list of conditions and the following disclaimer.
150c301abaSriastradh * 2. Redistributions in binary form must reproduce the above copyright
160c301abaSriastradh * notice, this list of conditions and the following disclaimer in the
170c301abaSriastradh * documentation and/or other materials provided with the distribution.
180c301abaSriastradh *
190c301abaSriastradh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
200c301abaSriastradh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
210c301abaSriastradh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220c301abaSriastradh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
230c301abaSriastradh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
240c301abaSriastradh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
250c301abaSriastradh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
260c301abaSriastradh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
270c301abaSriastradh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
280c301abaSriastradh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
290c301abaSriastradh * POSSIBILITY OF SUCH DAMAGE.
300c301abaSriastradh */
310c301abaSriastradh
320c301abaSriastradh /* Intel GTT stubs */
330c301abaSriastradh
340c301abaSriastradh #include <sys/cdefs.h>
35*f41a5bb1Sriastradh __KERNEL_RCSID(0, "$NetBSD: intel_gtt_subr.c,v 1.3 2021/12/19 12:37:36 riastradh Exp $");
360c301abaSriastradh
370c301abaSriastradh #include <sys/types.h>
380c301abaSriastradh #include <sys/bus.h>
390c301abaSriastradh #include <sys/errno.h>
400c301abaSriastradh #include <sys/systm.h>
410c301abaSriastradh
420c301abaSriastradh #include <machine/vmparam.h>
430c301abaSriastradh
440c301abaSriastradh #include <dev/pci/pcivar.h> /* XXX agpvar.h needs... */
450c301abaSriastradh #include <dev/pci/agpvar.h>
460c301abaSriastradh #include <dev/pci/agp_i810var.h>
470c301abaSriastradh
48c987c5e0Sriastradh #include <linux/pci.h>
490c301abaSriastradh #include <linux/scatterlist.h>
500c301abaSriastradh
51c987c5e0Sriastradh #include "drm/i915_drm.h"
520c301abaSriastradh #include "drm/intel-gtt.h"
530c301abaSriastradh
54c987c5e0Sriastradh static uint8_t
pci_conf_read8(pci_chipset_tag_t pc,pcitag_t tag,bus_size_t reg)55c987c5e0Sriastradh pci_conf_read8(pci_chipset_tag_t pc, pcitag_t tag, bus_size_t reg)
56c987c5e0Sriastradh {
57c987c5e0Sriastradh uint32_t v;
58c987c5e0Sriastradh
59c987c5e0Sriastradh v = pci_conf_read(pc, tag, reg & ~3);
60c987c5e0Sriastradh
61c987c5e0Sriastradh return 0xff & (v >> (8 * (reg & 3)));
62c987c5e0Sriastradh }
63c987c5e0Sriastradh
64c987c5e0Sriastradh static uint8_t
pci_read8(pci_chipset_tag_t pc,int bus,int dev,int func,bus_size_t reg)65c987c5e0Sriastradh pci_read8(pci_chipset_tag_t pc, int bus, int dev, int func, bus_size_t reg)
66c987c5e0Sriastradh {
67c987c5e0Sriastradh pcitag_t tag = pci_make_tag(pc, bus, dev, func);
68c987c5e0Sriastradh
69c987c5e0Sriastradh return pci_conf_read8(pc, tag, reg);
70c987c5e0Sriastradh }
71c987c5e0Sriastradh
72c987c5e0Sriastradh static uint16_t
pci_conf_read16(pci_chipset_tag_t pc,pcitag_t tag,bus_size_t reg)73c987c5e0Sriastradh pci_conf_read16(pci_chipset_tag_t pc, pcitag_t tag, bus_size_t reg)
74c987c5e0Sriastradh {
75c987c5e0Sriastradh uint32_t v;
76c987c5e0Sriastradh
77c987c5e0Sriastradh KASSERT((reg & 1) == 0);
78c987c5e0Sriastradh
79c987c5e0Sriastradh v = pci_conf_read(pc, tag, reg & ~2);
80c987c5e0Sriastradh
81c987c5e0Sriastradh return 0xffff & (v >> (8 * (reg & 2)));
82c987c5e0Sriastradh }
83c987c5e0Sriastradh
84c987c5e0Sriastradh static uint16_t
pci_read16(pci_chipset_tag_t pc,int bus,int dev,int func,bus_size_t reg)85c987c5e0Sriastradh pci_read16(pci_chipset_tag_t pc, int bus, int dev, int func, bus_size_t reg)
86c987c5e0Sriastradh {
87c987c5e0Sriastradh pcitag_t tag = pci_make_tag(pc, bus, dev, func);
88c987c5e0Sriastradh
89c987c5e0Sriastradh return pci_conf_read16(pc, tag, reg);
90c987c5e0Sriastradh }
91c987c5e0Sriastradh
920c301abaSriastradh /* Access to this should be single-threaded. */
930c301abaSriastradh static struct {
940c301abaSriastradh bus_dma_segment_t scratch_seg;
950c301abaSriastradh bus_dmamap_t scratch_map;
960c301abaSriastradh } intel_gtt;
970c301abaSriastradh
98c987c5e0Sriastradh /* XXX This logic should be merged with agp_i810.c. */
990c301abaSriastradh struct resource intel_graphics_stolen_res;
1000c301abaSriastradh
101c987c5e0Sriastradh static bus_size_t
i830_tseg_size(pci_chipset_tag_t pc)102c987c5e0Sriastradh i830_tseg_size(pci_chipset_tag_t pc)
103c987c5e0Sriastradh {
104c987c5e0Sriastradh uint8_t esmramc = pci_read8(pc, 0, 0, 0, I830_ESMRAMC);
105c987c5e0Sriastradh
106c987c5e0Sriastradh if ((esmramc & TSEG_ENABLE) == 0)
107c987c5e0Sriastradh return 0;
108c987c5e0Sriastradh
109c987c5e0Sriastradh return (esmramc & I830_TSEG_SIZE_1M) ? 1024*1024 : 512*1024;
110c987c5e0Sriastradh }
111c987c5e0Sriastradh
112c987c5e0Sriastradh static bus_size_t
i845_tseg_size(pci_chipset_tag_t pc)113c987c5e0Sriastradh i845_tseg_size(pci_chipset_tag_t pc)
114c987c5e0Sriastradh {
115c987c5e0Sriastradh uint8_t esmramc = pci_read8(pc, 0, 0, 0, I845_ESMRAMC);
116c987c5e0Sriastradh
117c987c5e0Sriastradh if ((esmramc & TSEG_ENABLE) == 0)
118c987c5e0Sriastradh return 0;
119c987c5e0Sriastradh
120c987c5e0Sriastradh switch (esmramc & I845_TSEG_SIZE_MASK) {
121c987c5e0Sriastradh case I845_TSEG_SIZE_512K:
122c987c5e0Sriastradh return 512*1024;
123c987c5e0Sriastradh case I845_TSEG_SIZE_1M:
124c987c5e0Sriastradh return 1024*1024;
125c987c5e0Sriastradh default:
126c987c5e0Sriastradh return 0;
127c987c5e0Sriastradh }
128c987c5e0Sriastradh }
129c987c5e0Sriastradh
130c987c5e0Sriastradh static bus_size_t
i85x_tseg_size(pci_chipset_tag_t pc)131c987c5e0Sriastradh i85x_tseg_size(pci_chipset_tag_t pc)
132c987c5e0Sriastradh {
133c987c5e0Sriastradh uint8_t esmramc = pci_read8(pc, 0, 0, 0, I85X_ESMRAMC);
134c987c5e0Sriastradh
135c987c5e0Sriastradh if ((esmramc & TSEG_ENABLE) == 0)
136c987c5e0Sriastradh return 0;
137c987c5e0Sriastradh
138c987c5e0Sriastradh return 1024*1024;
139c987c5e0Sriastradh }
140c987c5e0Sriastradh
141c987c5e0Sriastradh static bus_size_t
i830_tom(pci_chipset_tag_t pc)142c987c5e0Sriastradh i830_tom(pci_chipset_tag_t pc)
143c987c5e0Sriastradh {
144c987c5e0Sriastradh uint8_t drb3 = pci_read8(pc, 0, 0, 0, I830_DRB3);
145c987c5e0Sriastradh
146c987c5e0Sriastradh return (bus_size_t)32*1024*1024 * drb3;
147c987c5e0Sriastradh }
148c987c5e0Sriastradh
149c987c5e0Sriastradh static bus_size_t
i85x_tom(pci_chipset_tag_t pc)150c987c5e0Sriastradh i85x_tom(pci_chipset_tag_t pc)
151c987c5e0Sriastradh {
152c987c5e0Sriastradh uint8_t drb3 = pci_read8(pc, 0, 0, 1, I85X_DRB3);
153c987c5e0Sriastradh
154c987c5e0Sriastradh return (bus_size_t)32*1024*1024 * drb3;
155c987c5e0Sriastradh }
156c987c5e0Sriastradh
157c987c5e0Sriastradh static bus_size_t
i830_stolen_size(pci_chipset_tag_t pc,pcitag_t tag)158c987c5e0Sriastradh i830_stolen_size(pci_chipset_tag_t pc, pcitag_t tag)
159c987c5e0Sriastradh {
160c987c5e0Sriastradh uint16_t gmch_ctrl = pci_read16(pc, 0, 0, 0, I830_GMCH_CTRL);
161c987c5e0Sriastradh
162c987c5e0Sriastradh switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
163c987c5e0Sriastradh case I830_GMCH_GMS_STOLEN_512:
164c987c5e0Sriastradh return 512*1024;
165c987c5e0Sriastradh case I830_GMCH_GMS_STOLEN_1024:
166c987c5e0Sriastradh return 1024*1024;
167c987c5e0Sriastradh case I830_GMCH_GMS_STOLEN_8192:
168c987c5e0Sriastradh return 8*1024*1024;
169c987c5e0Sriastradh case I830_GMCH_GMS_LOCAL:
170c987c5e0Sriastradh default:
171c987c5e0Sriastradh aprint_error("%s: invalid gmch_ctrl 0x%04x\n", __func__,
172c987c5e0Sriastradh gmch_ctrl);
173c987c5e0Sriastradh return 0;
174c987c5e0Sriastradh }
175c987c5e0Sriastradh }
176c987c5e0Sriastradh
177c987c5e0Sriastradh static bus_size_t
gen3_stolen_size(pci_chipset_tag_t pc,pcitag_t tag)178c987c5e0Sriastradh gen3_stolen_size(pci_chipset_tag_t pc, pcitag_t tag)
179c987c5e0Sriastradh {
180c987c5e0Sriastradh uint16_t gmch_ctrl = pci_read16(pc, 0, 0, 0, I830_GMCH_CTRL);
181c987c5e0Sriastradh
182c987c5e0Sriastradh switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
183c987c5e0Sriastradh case I855_GMCH_GMS_STOLEN_1M:
184c987c5e0Sriastradh return 1024*1024;
185c987c5e0Sriastradh case I855_GMCH_GMS_STOLEN_4M:
186c987c5e0Sriastradh return 4*1024*1024;
187c987c5e0Sriastradh case I855_GMCH_GMS_STOLEN_8M:
188c987c5e0Sriastradh return 8*1024*1024;
189c987c5e0Sriastradh case I855_GMCH_GMS_STOLEN_16M:
190c987c5e0Sriastradh return 16*1024*1024;
191c987c5e0Sriastradh case I855_GMCH_GMS_STOLEN_32M:
192c987c5e0Sriastradh return 32*1024*1024;
193c987c5e0Sriastradh case I915_GMCH_GMS_STOLEN_48M:
194c987c5e0Sriastradh return 48*1024*1024;
195c987c5e0Sriastradh case I915_GMCH_GMS_STOLEN_64M:
196c987c5e0Sriastradh return 64*1024*1024;
197c987c5e0Sriastradh case G33_GMCH_GMS_STOLEN_128M:
198c987c5e0Sriastradh return 128*1024*1024;
199c987c5e0Sriastradh case G33_GMCH_GMS_STOLEN_256M:
200c987c5e0Sriastradh return 256*1024*1024;
201c987c5e0Sriastradh case INTEL_GMCH_GMS_STOLEN_96M:
202c987c5e0Sriastradh return 96*1024*1024;
203c987c5e0Sriastradh case INTEL_GMCH_GMS_STOLEN_160M:
204c987c5e0Sriastradh return 160*1024*1024;
205c987c5e0Sriastradh case INTEL_GMCH_GMS_STOLEN_224M:
206c987c5e0Sriastradh return 224*1024*1024;
207c987c5e0Sriastradh case INTEL_GMCH_GMS_STOLEN_352M:
208c987c5e0Sriastradh return 352*1024*1024;
209c987c5e0Sriastradh default:
210c987c5e0Sriastradh aprint_error("%s: invalid gmch_ctrl 0x%04x\n", __func__,
211c987c5e0Sriastradh gmch_ctrl);
212c987c5e0Sriastradh return 0;
213c987c5e0Sriastradh }
214c987c5e0Sriastradh }
215c987c5e0Sriastradh
216c987c5e0Sriastradh static bus_size_t
gen6_stolen_size(pci_chipset_tag_t pc,pcitag_t tag)217c987c5e0Sriastradh gen6_stolen_size(pci_chipset_tag_t pc, pcitag_t tag)
218c987c5e0Sriastradh {
219c987c5e0Sriastradh uint16_t gmch_ctrl = pci_conf_read16(pc, tag, SNB_GMCH_CTRL);
220c987c5e0Sriastradh uint16_t gms = (gmch_ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
221c987c5e0Sriastradh
222c987c5e0Sriastradh return (bus_size_t)32*1024*1024 * gms;
223c987c5e0Sriastradh }
224c987c5e0Sriastradh
225c987c5e0Sriastradh static bus_size_t
gen8_stolen_size(pci_chipset_tag_t pc,pcitag_t tag)226c987c5e0Sriastradh gen8_stolen_size(pci_chipset_tag_t pc, pcitag_t tag)
227c987c5e0Sriastradh {
228c987c5e0Sriastradh uint16_t gmch_ctrl = pci_conf_read16(pc, tag, SNB_GMCH_CTRL);
229c987c5e0Sriastradh uint16_t gms = (gmch_ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
230c987c5e0Sriastradh
231c987c5e0Sriastradh return (bus_size_t)32*1024*1024 * gms;
232c987c5e0Sriastradh }
233c987c5e0Sriastradh
234c987c5e0Sriastradh static bus_size_t
chv_stolen_size(pci_chipset_tag_t pc,pcitag_t tag)235c987c5e0Sriastradh chv_stolen_size(pci_chipset_tag_t pc, pcitag_t tag)
236c987c5e0Sriastradh {
237c987c5e0Sriastradh uint16_t gmch_ctrl = pci_conf_read16(pc, tag, SNB_GMCH_CTRL);
238c987c5e0Sriastradh uint16_t gms = (gmch_ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK;
239c987c5e0Sriastradh
240c987c5e0Sriastradh if (gms <= 0x10)
241c987c5e0Sriastradh return (bus_size_t)32*1024*1024 * gms;
242c987c5e0Sriastradh else if (gms <= 0x16)
243c987c5e0Sriastradh return (bus_size_t)(8 + 4*(gms - 0x11))*1024*1024;
244c987c5e0Sriastradh else
245c987c5e0Sriastradh return (bus_size_t)(36 + 4*(gms - 0x17))*1024*1024;
246c987c5e0Sriastradh }
247c987c5e0Sriastradh
248c987c5e0Sriastradh static bus_size_t
gen9_stolen_size(pci_chipset_tag_t pc,pcitag_t tag)249c987c5e0Sriastradh gen9_stolen_size(pci_chipset_tag_t pc, pcitag_t tag)
250c987c5e0Sriastradh {
251c987c5e0Sriastradh uint16_t gmch_ctrl = pci_conf_read16(pc, tag, SNB_GMCH_CTRL);
252c987c5e0Sriastradh uint16_t gms = (gmch_ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK;
253c987c5e0Sriastradh
254c987c5e0Sriastradh if (gms <= 0xef)
255c987c5e0Sriastradh return (bus_size_t)32*1024*1024 * gms;
256c987c5e0Sriastradh else
257c987c5e0Sriastradh return (bus_size_t)(4 + 4*(gms - 0xf0))*1024*1024;
258c987c5e0Sriastradh }
259c987c5e0Sriastradh
260c987c5e0Sriastradh static bus_addr_t
i830_stolen_base(pci_chipset_tag_t pc,pcitag_t tag,bus_size_t stolen_size)261c987c5e0Sriastradh i830_stolen_base(pci_chipset_tag_t pc, pcitag_t tag, bus_size_t stolen_size)
262c987c5e0Sriastradh {
263c987c5e0Sriastradh
264c987c5e0Sriastradh return i830_tom(pc) - i830_tseg_size(pc) - stolen_size;
265c987c5e0Sriastradh }
266c987c5e0Sriastradh
267c987c5e0Sriastradh static bus_addr_t
i845_stolen_base(pci_chipset_tag_t pc,pcitag_t tag,bus_size_t stolen_size)268c987c5e0Sriastradh i845_stolen_base(pci_chipset_tag_t pc, pcitag_t tag, bus_size_t stolen_size)
269c987c5e0Sriastradh {
270c987c5e0Sriastradh
271c987c5e0Sriastradh return i830_tom(pc) - i845_tseg_size(pc) - stolen_size;
272c987c5e0Sriastradh }
273c987c5e0Sriastradh
274c987c5e0Sriastradh static bus_addr_t
i85x_stolen_base(pci_chipset_tag_t pc,pcitag_t tag,bus_size_t stolen_size)275c987c5e0Sriastradh i85x_stolen_base(pci_chipset_tag_t pc, pcitag_t tag, bus_size_t stolen_size)
276c987c5e0Sriastradh {
277c987c5e0Sriastradh
278c987c5e0Sriastradh return i85x_tom(pc) - i85x_tseg_size(pc) - stolen_size;
279c987c5e0Sriastradh }
280c987c5e0Sriastradh
281c987c5e0Sriastradh static bus_addr_t
i865_stolen_base(pci_chipset_tag_t pc,pcitag_t tag,bus_size_t stolen_size)282c987c5e0Sriastradh i865_stolen_base(pci_chipset_tag_t pc, pcitag_t tag, bus_size_t stolen_size)
283c987c5e0Sriastradh {
284c987c5e0Sriastradh uint16_t toud = pci_read16(pc, 0, 0, 0, I865_TOUD);
285c987c5e0Sriastradh
286c987c5e0Sriastradh return i845_tseg_size(pc) + (64*1024 * toud);
287c987c5e0Sriastradh }
288c987c5e0Sriastradh
289c987c5e0Sriastradh static bus_addr_t
gen3_stolen_base(pci_chipset_tag_t pc,pcitag_t tag,bus_size_t stolen_size)290c987c5e0Sriastradh gen3_stolen_base(pci_chipset_tag_t pc, pcitag_t tag, bus_size_t stolen_size)
291c987c5e0Sriastradh {
292c987c5e0Sriastradh uint32_t bsm = pci_conf_read(pc, tag, INTEL_BSM);
293c987c5e0Sriastradh
294c987c5e0Sriastradh return bsm & INTEL_BSM_MASK;
295c987c5e0Sriastradh }
296c987c5e0Sriastradh
297c987c5e0Sriastradh static bus_addr_t
gen11_stolen_base(pci_chipset_tag_t pc,pcitag_t tag,bus_size_t stolen_size)298c987c5e0Sriastradh gen11_stolen_base(pci_chipset_tag_t pc, pcitag_t tag, bus_size_t stolen_size)
299c987c5e0Sriastradh {
300c987c5e0Sriastradh uint32_t bsm;
301c987c5e0Sriastradh
302c987c5e0Sriastradh bsm = pci_conf_read(pc, tag, INTEL_GEN11_BSM_DW0) & INTEL_BSM_MASK;
303c987c5e0Sriastradh bsm |= (uint64_t)pci_conf_read(pc, tag, INTEL_GEN11_BSM_DW1) << 32;
304c987c5e0Sriastradh
305c987c5e0Sriastradh return bsm;
306c987c5e0Sriastradh }
307c987c5e0Sriastradh
308c987c5e0Sriastradh struct intel_stolen_ops {
309c987c5e0Sriastradh bus_size_t (*size)(pci_chipset_tag_t, pcitag_t);
310c987c5e0Sriastradh bus_addr_t (*base)(pci_chipset_tag_t, pcitag_t, bus_size_t);
311c987c5e0Sriastradh };
312c987c5e0Sriastradh
313c987c5e0Sriastradh static const struct intel_stolen_ops i830_stolen_ops = {
314c987c5e0Sriastradh .size = i830_stolen_size,
315c987c5e0Sriastradh .base = i830_stolen_base,
316c987c5e0Sriastradh };
317c987c5e0Sriastradh
318c987c5e0Sriastradh static const struct intel_stolen_ops i845_stolen_ops = {
319c987c5e0Sriastradh .size = i830_stolen_size,
320c987c5e0Sriastradh .base = i845_stolen_base,
321c987c5e0Sriastradh };
322c987c5e0Sriastradh
323c987c5e0Sriastradh static const struct intel_stolen_ops i85x_stolen_ops = {
324c987c5e0Sriastradh .size = gen3_stolen_size,
325c987c5e0Sriastradh .base = i85x_stolen_base,
326c987c5e0Sriastradh };
327c987c5e0Sriastradh
328c987c5e0Sriastradh static const struct intel_stolen_ops i865_stolen_ops = {
329c987c5e0Sriastradh .size = gen3_stolen_size,
330c987c5e0Sriastradh .base = i865_stolen_base,
331c987c5e0Sriastradh };
332c987c5e0Sriastradh
333c987c5e0Sriastradh static const struct intel_stolen_ops gen3_stolen_ops = {
334c987c5e0Sriastradh .size = gen3_stolen_size,
335c987c5e0Sriastradh .base = gen3_stolen_base,
336c987c5e0Sriastradh };
337c987c5e0Sriastradh
338c987c5e0Sriastradh static const struct intel_stolen_ops gen6_stolen_ops = {
339c987c5e0Sriastradh .size = gen6_stolen_size,
340c987c5e0Sriastradh .base = gen3_stolen_base,
341c987c5e0Sriastradh };
342c987c5e0Sriastradh
343c987c5e0Sriastradh static const struct intel_stolen_ops gen8_stolen_ops = {
344c987c5e0Sriastradh .size = gen8_stolen_size,
345c987c5e0Sriastradh .base = gen3_stolen_base,
346c987c5e0Sriastradh };
347c987c5e0Sriastradh
348c987c5e0Sriastradh static const struct intel_stolen_ops gen9_stolen_ops = {
349c987c5e0Sriastradh .size = gen9_stolen_size,
350c987c5e0Sriastradh .base = gen3_stolen_base,
351c987c5e0Sriastradh };
352c987c5e0Sriastradh
353c987c5e0Sriastradh static const struct intel_stolen_ops chv_stolen_ops = {
354c987c5e0Sriastradh .size = chv_stolen_size,
355c987c5e0Sriastradh .base = gen3_stolen_base,
356c987c5e0Sriastradh };
357c987c5e0Sriastradh
358c987c5e0Sriastradh static const struct intel_stolen_ops gen11_stolen_ops = {
359c987c5e0Sriastradh .size = gen9_stolen_size,
360c987c5e0Sriastradh .base = gen11_stolen_base,
361c987c5e0Sriastradh };
362c987c5e0Sriastradh
363c987c5e0Sriastradh static const struct pci_device_id intel_stolen_ids[] = {
364c987c5e0Sriastradh INTEL_I830_IDS(&i830_stolen_ops),
365c987c5e0Sriastradh INTEL_I845G_IDS(&i845_stolen_ops),
366c987c5e0Sriastradh INTEL_I85X_IDS(&i85x_stolen_ops),
367c987c5e0Sriastradh INTEL_I865G_IDS(&i865_stolen_ops),
368c987c5e0Sriastradh INTEL_I915G_IDS(&gen3_stolen_ops),
369c987c5e0Sriastradh INTEL_I915GM_IDS(&gen3_stolen_ops),
370c987c5e0Sriastradh INTEL_I945G_IDS(&gen3_stolen_ops),
371c987c5e0Sriastradh INTEL_I945GM_IDS(&gen3_stolen_ops),
372c987c5e0Sriastradh INTEL_VLV_IDS(&gen6_stolen_ops),
373c987c5e0Sriastradh INTEL_PINEVIEW_G_IDS(&gen3_stolen_ops),
374c987c5e0Sriastradh INTEL_PINEVIEW_M_IDS(&gen3_stolen_ops),
375c987c5e0Sriastradh INTEL_I965G_IDS(&gen3_stolen_ops),
376c987c5e0Sriastradh INTEL_G33_IDS(&gen3_stolen_ops),
377c987c5e0Sriastradh INTEL_I965GM_IDS(&gen3_stolen_ops),
378c987c5e0Sriastradh INTEL_GM45_IDS(&gen3_stolen_ops),
379c987c5e0Sriastradh INTEL_G45_IDS(&gen3_stolen_ops),
380c987c5e0Sriastradh INTEL_IRONLAKE_D_IDS(&gen3_stolen_ops),
381c987c5e0Sriastradh INTEL_IRONLAKE_M_IDS(&gen3_stolen_ops),
382c987c5e0Sriastradh INTEL_SNB_D_IDS(&gen6_stolen_ops),
383c987c5e0Sriastradh INTEL_SNB_M_IDS(&gen6_stolen_ops),
384c987c5e0Sriastradh INTEL_IVB_M_IDS(&gen6_stolen_ops),
385c987c5e0Sriastradh INTEL_IVB_D_IDS(&gen6_stolen_ops),
386c987c5e0Sriastradh INTEL_HSW_IDS(&gen6_stolen_ops),
387c987c5e0Sriastradh INTEL_BDW_IDS(&gen8_stolen_ops),
388c987c5e0Sriastradh INTEL_CHV_IDS(&chv_stolen_ops),
389c987c5e0Sriastradh INTEL_SKL_IDS(&gen9_stolen_ops),
390c987c5e0Sriastradh INTEL_BXT_IDS(&gen9_stolen_ops),
391c987c5e0Sriastradh INTEL_KBL_IDS(&gen9_stolen_ops),
392c987c5e0Sriastradh INTEL_CFL_IDS(&gen9_stolen_ops),
393c987c5e0Sriastradh INTEL_GLK_IDS(&gen9_stolen_ops),
394c987c5e0Sriastradh INTEL_CNL_IDS(&gen9_stolen_ops),
395c987c5e0Sriastradh INTEL_ICL_11_IDS(&gen11_stolen_ops),
396c987c5e0Sriastradh INTEL_EHL_IDS(&gen11_stolen_ops),
397c987c5e0Sriastradh INTEL_TGL_12_IDS(&gen11_stolen_ops),
398c987c5e0Sriastradh };
399c987c5e0Sriastradh
4000c301abaSriastradh void
intel_gtt_get(uint64_t * va_size,bus_addr_t * aper_base,resource_size_t * aper_size)401*f41a5bb1Sriastradh intel_gtt_get(uint64_t *va_size, bus_addr_t *aper_base,
402*f41a5bb1Sriastradh resource_size_t *aper_size)
4030c301abaSriastradh {
404c987c5e0Sriastradh struct agp_softc *sc;
405c987c5e0Sriastradh pci_chipset_tag_t pc;
406c987c5e0Sriastradh pcitag_t tag;
407c987c5e0Sriastradh struct agp_i810_softc *isc;
408c987c5e0Sriastradh const struct intel_stolen_ops *ops;
409c987c5e0Sriastradh bus_addr_t stolen_base;
410c987c5e0Sriastradh bus_size_t stolen_size;
411c987c5e0Sriastradh unsigned i;
4120c301abaSriastradh
413c987c5e0Sriastradh if ((sc = agp_i810_sc) == NULL) {
4140c301abaSriastradh *va_size = 0;
4150c301abaSriastradh *aper_base = 0;
4160c301abaSriastradh *aper_size = 0;
4170c301abaSriastradh return;
4180c301abaSriastradh }
4190c301abaSriastradh
420c987c5e0Sriastradh pc = sc->as_pc;
421c987c5e0Sriastradh tag = sc->as_tag;
422c987c5e0Sriastradh
423c987c5e0Sriastradh isc = sc->as_chipc;
4240c301abaSriastradh *va_size = ((size_t)(isc->gtt_size/sizeof(uint32_t)) << PAGE_SHIFT);
4250c301abaSriastradh *aper_base = sc->as_apaddr;
4260c301abaSriastradh *aper_size = sc->as_apsize;
4270c301abaSriastradh
428c987c5e0Sriastradh for (i = 0; i < __arraycount(intel_stolen_ids); i++) {
429c987c5e0Sriastradh if (intel_stolen_ids[i].device == PCI_PRODUCT(sc->as_id)) {
430c987c5e0Sriastradh ops = (const struct intel_stolen_ops *)
431c987c5e0Sriastradh intel_stolen_ids[i].driver_data;
432c987c5e0Sriastradh stolen_size = (*ops->size)(pc, tag);
433c987c5e0Sriastradh stolen_base = (*ops->base)(pc, tag, stolen_size);
434c987c5e0Sriastradh intel_graphics_stolen_res.start = stolen_base;
435c987c5e0Sriastradh intel_graphics_stolen_res.end =
436c987c5e0Sriastradh stolen_base + stolen_size - 1;
437c987c5e0Sriastradh break;
438c987c5e0Sriastradh }
439c987c5e0Sriastradh }
4400c301abaSriastradh }
4410c301abaSriastradh
4420c301abaSriastradh int
intel_gmch_probe(struct pci_dev * bridge_pci __unused,struct pci_dev * gpu __unused,struct agp_bridge_data * bridge_agp __unused)4430c301abaSriastradh intel_gmch_probe(struct pci_dev *bridge_pci __unused,
4440c301abaSriastradh struct pci_dev *gpu __unused, struct agp_bridge_data *bridge_agp __unused)
4450c301abaSriastradh {
4460c301abaSriastradh struct agp_softc *const sc = agp_i810_sc;
4470c301abaSriastradh int nsegs;
4480c301abaSriastradh int error;
4490c301abaSriastradh
4500c301abaSriastradh if (sc == NULL)
4510c301abaSriastradh return 0;
4520c301abaSriastradh
4530c301abaSriastradh error = bus_dmamem_alloc(sc->as_dmat, PAGE_SIZE, PAGE_SIZE, 0,
4540c301abaSriastradh &intel_gtt.scratch_seg, 1, &nsegs, BUS_DMA_WAITOK);
4550c301abaSriastradh if (error)
4560c301abaSriastradh goto fail0;
4570c301abaSriastradh KASSERT(nsegs == 1);
4580c301abaSriastradh
4590c301abaSriastradh error = bus_dmamap_create(sc->as_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
4600c301abaSriastradh BUS_DMA_WAITOK, &intel_gtt.scratch_map);
4610c301abaSriastradh if (error)
4620c301abaSriastradh goto fail1;
4630c301abaSriastradh
4640c301abaSriastradh error = bus_dmamap_load_raw(sc->as_dmat, intel_gtt.scratch_map,
4650c301abaSriastradh &intel_gtt.scratch_seg, 1, PAGE_SIZE, BUS_DMA_WAITOK);
4660c301abaSriastradh if (error)
4670c301abaSriastradh goto fail2;
4680c301abaSriastradh
4690c301abaSriastradh /* Success! */
4700c301abaSriastradh return 1;
4710c301abaSriastradh
4720c301abaSriastradh fail3: __unused
4730c301abaSriastradh bus_dmamap_unload(sc->as_dmat, intel_gtt.scratch_map);
4740c301abaSriastradh fail2: bus_dmamap_destroy(sc->as_dmat, intel_gtt.scratch_map);
4750c301abaSriastradh fail1: bus_dmamem_free(sc->as_dmat, &intel_gtt.scratch_seg, 1);
4760c301abaSriastradh fail0: KASSERT(error);
4770c301abaSriastradh return 0;
4780c301abaSriastradh }
4790c301abaSriastradh
4800c301abaSriastradh void
intel_gmch_remove(void)4810c301abaSriastradh intel_gmch_remove(void)
4820c301abaSriastradh {
4830c301abaSriastradh struct agp_softc *const sc = agp_i810_sc;
4840c301abaSriastradh
4850c301abaSriastradh bus_dmamap_unload(sc->as_dmat, intel_gtt.scratch_map);
4860c301abaSriastradh bus_dmamap_destroy(sc->as_dmat, intel_gtt.scratch_map);
4870c301abaSriastradh bus_dmamem_free(sc->as_dmat, &intel_gtt.scratch_seg, 1);
4880c301abaSriastradh }
4890c301abaSriastradh
4900c301abaSriastradh bool
intel_enable_gtt(void)4910c301abaSriastradh intel_enable_gtt(void)
4920c301abaSriastradh {
4930c301abaSriastradh struct agp_softc *sc = agp_i810_sc;
4940c301abaSriastradh struct agp_i810_softc *isc;
4950c301abaSriastradh
4960c301abaSriastradh if (sc == NULL)
4970c301abaSriastradh return false;
4980c301abaSriastradh isc = sc->as_chipc;
4990c301abaSriastradh agp_i810_reset(isc);
5000c301abaSriastradh return true;
5010c301abaSriastradh }
5020c301abaSriastradh
5030c301abaSriastradh void
intel_gtt_chipset_flush(void)5040c301abaSriastradh intel_gtt_chipset_flush(void)
5050c301abaSriastradh {
5060c301abaSriastradh
5070c301abaSriastradh KASSERT(agp_i810_sc != NULL);
5080c301abaSriastradh agp_i810_chipset_flush(agp_i810_sc->as_chipc);
5090c301abaSriastradh }
5100c301abaSriastradh
5110c301abaSriastradh static int
intel_gtt_flags(unsigned flags)5120c301abaSriastradh intel_gtt_flags(unsigned flags)
5130c301abaSriastradh {
5140c301abaSriastradh int gtt_flags = AGP_I810_GTT_VALID;
5150c301abaSriastradh
5160c301abaSriastradh switch (flags) {
5170c301abaSriastradh case AGP_USER_MEMORY:
5180c301abaSriastradh break;
5190c301abaSriastradh case AGP_USER_CACHED_MEMORY:
5200c301abaSriastradh gtt_flags |= AGP_I810_GTT_CACHED;
5210c301abaSriastradh break;
5220c301abaSriastradh default:
5230c301abaSriastradh panic("invalid intel gtt flags: %x", flags);
5240c301abaSriastradh }
5250c301abaSriastradh
5260c301abaSriastradh return gtt_flags;
5270c301abaSriastradh }
5280c301abaSriastradh
5290c301abaSriastradh void
intel_gtt_insert_page(bus_addr_t addr,unsigned va_page,unsigned flags)5300c301abaSriastradh intel_gtt_insert_page(bus_addr_t addr, unsigned va_page, unsigned flags)
5310c301abaSriastradh {
5320c301abaSriastradh struct agp_i810_softc *const isc = agp_i810_sc->as_chipc;
5330c301abaSriastradh off_t va = (off_t)va_page << PAGE_SHIFT;
5340c301abaSriastradh int gtt_flags = intel_gtt_flags(flags);
5350c301abaSriastradh int error;
5360c301abaSriastradh
5370c301abaSriastradh error = agp_i810_write_gtt_entry(isc, va, addr, gtt_flags);
5380c301abaSriastradh if (error)
5390c301abaSriastradh device_printf(agp_i810_sc->as_dev,
5400c301abaSriastradh "write gtt entry"
5410c301abaSriastradh " %"PRIxMAX" -> %"PRIxMAX" (flags=%x) failed: %d\n",
5420c301abaSriastradh (uintmax_t)va, (uintmax_t)addr, flags,
5430c301abaSriastradh error);
5440c301abaSriastradh agp_i810_post_gtt_entry(isc, va);
5450c301abaSriastradh intel_gtt_chipset_flush();
5460c301abaSriastradh }
5470c301abaSriastradh
5480c301abaSriastradh void
intel_gtt_insert_sg_entries(struct sg_table * sg,unsigned va_page,unsigned flags)5490c301abaSriastradh intel_gtt_insert_sg_entries(struct sg_table *sg, unsigned va_page,
5500c301abaSriastradh unsigned flags)
5510c301abaSriastradh {
5520c301abaSriastradh bus_dmamap_t dmamap = sg->sgl[0].sg_dmamap;
5530c301abaSriastradh struct agp_i810_softc *const isc = agp_i810_sc->as_chipc;
5540c301abaSriastradh off_t va = (off_t)va_page << PAGE_SHIFT;
5550c301abaSriastradh unsigned seg;
5560c301abaSriastradh int gtt_flags = intel_gtt_flags(flags);
5570c301abaSriastradh int error;
5580c301abaSriastradh
5590c301abaSriastradh KASSERT(0 <= va);
5600c301abaSriastradh KASSERT((va >> PAGE_SHIFT) == va_page);
5610c301abaSriastradh KASSERT(0 < dmamap->dm_nsegs);
5620c301abaSriastradh
5630c301abaSriastradh for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
5640c301abaSriastradh const bus_addr_t addr = dmamap->dm_segs[seg].ds_addr;
5650c301abaSriastradh bus_size_t len;
5660c301abaSriastradh
5670c301abaSriastradh for (len = dmamap->dm_segs[seg].ds_len;
5680c301abaSriastradh len >= PAGE_SIZE;
5690c301abaSriastradh len -= PAGE_SIZE, va += PAGE_SIZE) {
5700c301abaSriastradh error = agp_i810_write_gtt_entry(isc, va, addr,
5710c301abaSriastradh gtt_flags);
5720c301abaSriastradh if (error)
5730c301abaSriastradh device_printf(agp_i810_sc->as_dev,
5740c301abaSriastradh "write gtt entry"
5750c301abaSriastradh " %"PRIxMAX" -> %"PRIxMAX" (flags=%x)"
5760c301abaSriastradh " failed: %d\n",
5770c301abaSriastradh (uintmax_t)va, (uintmax_t)addr, flags,
5780c301abaSriastradh error);
5790c301abaSriastradh }
5800c301abaSriastradh KASSERTMSG(len == 0,
5810c301abaSriastradh "segment length not divisible by PAGE_SIZE: %jx",
5820c301abaSriastradh (uintmax_t)dmamap->dm_segs[seg].ds_len);
5830c301abaSriastradh }
5840c301abaSriastradh agp_i810_post_gtt_entry(isc, (va - PAGE_SIZE));
5850c301abaSriastradh intel_gtt_chipset_flush();
5860c301abaSriastradh }
5870c301abaSriastradh
5880c301abaSriastradh void
intel_gtt_clear_range(unsigned va_page,unsigned npages)5890c301abaSriastradh intel_gtt_clear_range(unsigned va_page, unsigned npages)
5900c301abaSriastradh {
5910c301abaSriastradh struct agp_i810_softc *const isc = agp_i810_sc->as_chipc;
5920c301abaSriastradh const bus_addr_t addr = intel_gtt.scratch_map->dm_segs[0].ds_addr;
5930c301abaSriastradh const int gtt_flags = AGP_I810_GTT_VALID;
5940c301abaSriastradh off_t va = (va_page << PAGE_SHIFT);
5950c301abaSriastradh
5960c301abaSriastradh KASSERT(0 <= va);
5970c301abaSriastradh KASSERT((va >> PAGE_SHIFT) == va_page);
5980c301abaSriastradh KASSERT(0 < npages);
5990c301abaSriastradh
6000c301abaSriastradh while (npages--) {
6010c301abaSriastradh agp_i810_write_gtt_entry(isc, va, addr, gtt_flags);
6020c301abaSriastradh va += PAGE_SIZE;
6030c301abaSriastradh }
6040c301abaSriastradh agp_i810_post_gtt_entry(isc, va - PAGE_SIZE);
6050c301abaSriastradh }
606