xref: /gfx-drm/usr/src/uts/intel/io/agpmaster/agpmaster.c (revision 3db4bae9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2009, Intel Corporation.
24  * All Rights Reserved.
25  */
26 
27 /*
28  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
29  * Use is subject to license terms.
30  */
31 
32 /*
33  * Misc module for AGP master device support
34  */
35 
36 #include <sys/modctl.h>
37 #include <sys/pci.h>
38 #include <sys/stat.h>
39 #include <sys/file.h>
40 #include <sys/types.h>
41 #include <sys/dditypes.h>
42 #include <sys/sunddi.h>
43 #include <sys/agpgart.h>
44 #include <sys/agp/agpdefs.h>
45 #include <sys/agp/agpmaster_io.h>
46 
47 #define	PGTBL_CTL	0x2020	/* Page table control register */
48 #define	I8XX_FB_BAR	1
49 #define	I8XX_MMIO_BAR	2
50 #define	I8XX_PTE_OFFSET	0x10000
51 #define	I915_MMADR	1	/* mem-mapped registers BAR */
52 #define	I915_GMADR	3	/* graphics mem BAR */
53 #define	I915_GTTADDR	4	/* GTT BAR */
54 #define	I965_GTTMMADR	1	/* mem-mapped registers BAR + GTT */
55 /* In 965 1MB GTTMMADR, GTT reside in the latter 512KB */
56 #define	I965_GTT_OFFSET	0x80000
57 #define	GM45_GTT_OFFSET	0x200000
58 #define	GTT_SIZE_MASK	0xe
59 #define	GTT_512KB	(0 << 1)
60 #define	GTT_256KB	(1 << 1)
61 #define	GTT_128KB	(2 << 1)
62 #define	GTT_1MB		(3 << 1)
63 #define	GTT_2MB		(4 << 1)
64 #define	GTT_1_5MB	(5 << 1)
65 
66 #define	MMIO_BASE(x)	(x)->agpm_data.agpm_gtt.gtt_mmio_base
67 #define	MMIO_HANDLE(x)	(x)->agpm_data.agpm_gtt.gtt_mmio_handle
68 #define	GTT_HANDLE(x)	(x)->agpm_data.agpm_gtt.gtt_handle
69 /* Base address of GTT */
70 #define	GTT_ADDR(x)	(x)->agpm_data.agpm_gtt.gtt_addr
71 /* Graphics memory base address */
72 #define	APER_BASE(x)	(x)->agpm_data.agpm_gtt.gtt_info.igd_aperbase
73 
74 #define	AGPM_WRITE(x, off, val) \
75     ddi_put32(MMIO_HANDLE(x), (uint32_t *)(MMIO_BASE(x) + (off)), (val));
76 
77 #define	AGPM_READ(x, off) \
78     ddi_get32(MMIO_HANDLE(x), (uint32_t *)(MMIO_BASE(x) + (off)));
79 
80 #ifdef DEBUG
81 #define	CONFIRM(value) ASSERT(value)
82 #else
83 #define	CONFIRM(value) if (!(value)) return (EINVAL)
84 #endif
85 
86 int agpm_debug = 0;
87 #define	AGPM_DEBUG(args)	if (agpm_debug >= 1) cmn_err args
88 
89 /*
90  * Whether it is a Intel integrated graphics card
91  */
92 #define	IS_IGD(agpmaster) ((agpmaster->agpm_dev_type == DEVICE_IS_I810) || \
93 	(agpmaster->agpm_dev_type == DEVICE_IS_I830))
94 
95 static struct modlmisc modlmisc = {
96 	&mod_miscops, "AGP master interfaces"
97 };
98 
99 static struct modlinkage modlinkage = {
100 	MODREV_1, (void *)&modlmisc, NULL
101 };
102 
103 static ddi_device_acc_attr_t i8xx_dev_access = {
104 	DDI_DEVICE_ATTR_V0,
105 	DDI_NEVERSWAP_ACC,
106 	DDI_STRICTORDER_ACC
107 };
108 
109 static off_t agpmaster_cap_find(ddi_acc_handle_t);
110 static int detect_i8xx_device(agp_master_softc_t *);
111 static int detect_agp_devcice(agp_master_softc_t *, ddi_acc_handle_t);
112 static int i8xx_add_to_gtt(gtt_impl_t *, igd_gtt_seg_t);
113 static void i8xx_remove_from_gtt(gtt_impl_t *, igd_gtt_seg_t);
114 static int i8xx_read_gtt(gtt_impl_t *, igd_gtt_seg_t);
115 static int i8xx_write_gtt(gtt_impl_t *, igd_gtt_seg_t);
116 
117 int
_init(void)118 _init(void)
119 {
120 	int	err;
121 
122 	if ((err = mod_install(&modlinkage)) != 0)
123 		return (err);
124 
125 	return (0);
126 }
127 
128 int
_fini(void)129 _fini(void)
130 {
131 	int	err;
132 
133 	if ((err = mod_remove(&modlinkage)) != 0)
134 		return (err);
135 
136 	return (0);
137 }
138 
139 int
_info(struct modinfo * modinfop)140 _info(struct modinfo *modinfop)
141 {
142 	return (mod_info(&modlinkage, modinfop));
143 }
144 
145 /*
146  * Minor node is not removed here, since the caller (xx_attach) is
147  * responsible for removing all nodes.
148  */
149 void
agpmaster_detach(agp_master_softc_t ** master_softcp)150 agpmaster_detach(agp_master_softc_t **master_softcp)
151 {
152 	agp_master_softc_t *master_softc;
153 
154 	ASSERT(master_softcp);
155 	master_softc = *master_softcp;
156 
157 	/* intel integrated device */
158 	if (IS_IGD(master_softc) &&
159 	    ((MMIO_HANDLE(master_softc) != NULL) ||
160 	    (GTT_HANDLE(master_softc) != NULL))) {
161 		/*
162 		 * for some chipsets, mmap handle is shared between both mmio
163 		 * and GTT table.
164 		 */
165 		if ((GTT_HANDLE(master_softc) != MMIO_HANDLE(master_softc)) &&
166 		    (GTT_HANDLE(master_softc) != NULL))
167 			ddi_regs_map_free(&GTT_HANDLE(master_softc));
168 		if (MMIO_HANDLE(master_softc) != NULL)
169 			ddi_regs_map_free(&MMIO_HANDLE(master_softc));
170 	}
171 
172 	kmem_free(master_softc, sizeof (agp_master_softc_t));
173 	master_softc = NULL;
174 
175 	return;
176 
177 }
178 
179 /*
180  * 965 has a fixed GTT table size (512KB), so check to see the actual aperture
181  * size. Aperture size = GTT table size * 1024.
182  */
183 static off_t
i965_apersize(agp_master_softc_t * agpmaster)184 i965_apersize(agp_master_softc_t *agpmaster)
185 {
186 	off_t apersize;
187 
188 	apersize = AGPM_READ(agpmaster, PGTBL_CTL);
189 	AGPM_DEBUG((CE_NOTE, "i965_apersize: PGTBL_CTL = %lx", apersize));
190 	switch (apersize & GTT_SIZE_MASK) {
191 	case GTT_2MB:
192 		apersize = 2048;
193 		break;
194 	case GTT_1_5MB:
195 		apersize = 1536;
196 		break;
197 	case GTT_1MB:
198 		apersize = 1024;
199 		break;
200 	case GTT_512KB:
201 		apersize = 512;
202 		break;
203 	case GTT_256KB:
204 		apersize = 256;
205 		break;
206 	case GTT_128KB:
207 		apersize = 128;
208 		break;
209 	default:
210 		apersize = 0;
211 		AGPM_DEBUG((CE_WARN,
212 		    "i965_apersize: invalid GTT size in PGTBL_CTL"));
213 	}
214 	return (apersize);
215 }
216 
217 /*
218  * For Intel 3 series, we need to get GTT size from the GGMS field in GMCH
219  * Graphics Control Register. Return aperture size in MB.
220  */
221 static off_t
i3XX_apersize(ddi_acc_handle_t pci_acc_hdl)222 i3XX_apersize(ddi_acc_handle_t pci_acc_hdl)
223 {
224 	uint16_t value;
225 	off_t apersize;
226 
227 	/*
228 	 * Get the value of configuration register MGGC "Mirror of Dev0 GMCH
229 	 * Graphics Control" from Internal Graphics #2 (Device2:Function0).
230 	 */
231 	value = pci_config_get16(pci_acc_hdl, I8XX_CONF_GC);
232 	AGPM_DEBUG((CE_NOTE, "i3XX_apersize: MGGC = 0x%x", value));
233 	/* computing aperture size using the pre-allocated GTT size */
234 	switch (value & IX33_GGMS_MASK) {
235 	case IX33_GGMS_1M:
236 		apersize = 1024;
237 		break;
238 	case IX33_GGMS_2M:
239 		apersize = 2048;
240 		break;
241 	default:
242 		apersize = 0;	/* no memory pre-allocated */
243 		AGPM_DEBUG((CE_WARN,
244 		    "i3XX_apersize: no memory allocated for GTT"));
245 	}
246 	AGPM_DEBUG((CE_NOTE, "i3xx_apersize: apersize = %ldM", apersize));
247 	return (apersize);
248 }
249 
250 #define	CHECK_STATUS(status)	\
251     if (status != DDI_SUCCESS) { \
252 	    AGPM_DEBUG((CE_WARN, \
253 		"set_gtt_mmio: regs_map_setup error")); \
254 	    return (-1); \
255 }
256 /*
257  * Set gtt_addr, gtt_mmio_base, igd_apersize, igd_aperbase and igd_devid
258  * according to chipset.
259  */
260 static int
set_gtt_mmio(dev_info_t * devi,agp_master_softc_t * agpmaster,ddi_acc_handle_t pci_acc_hdl)261 set_gtt_mmio(dev_info_t *devi, agp_master_softc_t *agpmaster,
262     ddi_acc_handle_t pci_acc_hdl)
263 {
264 	off_t apersize;  /* size of graphics mem (MB) == GTT size (KB) */
265 	uint32_t value;
266 	off_t gmadr_off;  /* GMADR offset in PCI config space */
267 	int status;
268 
269 	if (IS_INTEL_X33(agpmaster->agpm_id)) {
270 		/* Intel 3 series are similar with 915/945 series */
271 		status = ddi_regs_map_setup(devi, I915_GTTADDR,
272 		    &GTT_ADDR(agpmaster), 0, 0, &i8xx_dev_access,
273 		    &GTT_HANDLE(agpmaster));
274 		CHECK_STATUS(status);
275 
276 		status = ddi_regs_map_setup(devi, I915_MMADR,
277 		    &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access,
278 		    &MMIO_HANDLE(agpmaster));
279 		CHECK_STATUS(status);
280 
281 		gmadr_off = I915_CONF_GMADR;
282 		/* Different computing method used in getting aperture size. */
283 		apersize = i3XX_apersize(pci_acc_hdl);
284 	} else if (IS_INTEL_965(agpmaster->agpm_id)) {
285 		status = ddi_regs_map_setup(devi, I965_GTTMMADR,
286 		    &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access,
287 		    &MMIO_HANDLE(agpmaster));
288 		CHECK_STATUS(status);
289 		if ((agpmaster->agpm_id == INTEL_IGD_GM45) ||
290 		    IS_INTEL_G4X(agpmaster->agpm_id))
291 			GTT_ADDR(agpmaster) =
292 			    MMIO_BASE(agpmaster) + GM45_GTT_OFFSET;
293 		else
294 			GTT_ADDR(agpmaster) =
295 			    MMIO_BASE(agpmaster) + I965_GTT_OFFSET;
296 		GTT_HANDLE(agpmaster) = MMIO_HANDLE(agpmaster);
297 
298 		gmadr_off = I915_CONF_GMADR;
299 		apersize = i965_apersize(agpmaster);
300 	} else if (IS_INTEL_915(agpmaster->agpm_id)) {
301 		/* I915/945 series */
302 		status = ddi_regs_map_setup(devi, I915_GTTADDR,
303 		    &GTT_ADDR(agpmaster), 0, 0, &i8xx_dev_access,
304 		    &GTT_HANDLE(agpmaster));
305 		CHECK_STATUS(status);
306 
307 		status = ddi_regs_map_setup(devi, I915_MMADR,
308 		    &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access,
309 		    &MMIO_HANDLE(agpmaster));
310 		CHECK_STATUS(status);
311 
312 		gmadr_off = I915_CONF_GMADR;
313 		status = ddi_dev_regsize(devi, I915_GMADR, &apersize);
314 		apersize = BYTES2MB(apersize);
315 	} else {
316 		/* I8XX series */
317 		status = ddi_regs_map_setup(devi, I8XX_MMIO_BAR,
318 		    &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access,
319 		    &MMIO_HANDLE(agpmaster));
320 		CHECK_STATUS(status);
321 
322 		GTT_ADDR(agpmaster) = MMIO_BASE(agpmaster) + I8XX_PTE_OFFSET;
323 		GTT_HANDLE(agpmaster) = MMIO_HANDLE(agpmaster);
324 		gmadr_off = I8XX_CONF_GMADR;
325 		status = ddi_dev_regsize(devi, I8XX_FB_BAR, &apersize);
326 		apersize = BYTES2MB(apersize);
327 		CHECK_STATUS(status);
328 	}
329 
330 	/*
331 	 * If memory size is smaller than a certain value, it means
332 	 * the register set number for graphics memory range might
333 	 * be wrong
334 	 */
335 	if (status != DDI_SUCCESS || apersize < 4) {
336 		AGPM_DEBUG((CE_WARN,
337 		    "set_gtt_mmio: error in getting graphics memory"));
338 		return (-1);
339 	}
340 
341 	agpmaster->agpm_data.agpm_gtt.gtt_info.igd_apersize = apersize;
342 
343 	/* get graphics memory base address from GMADR */
344 	value = pci_config_get32(pci_acc_hdl, gmadr_off);
345 	APER_BASE(agpmaster) = value & GTT_BASE_MASK;
346 	AGPM_DEBUG((CE_NOTE, "set_gtt_mmio: aperbase = 0x%x, apersize = %ldM, "
347 	    "gtt_addr = %p, mmio_base = %p", APER_BASE(agpmaster), apersize,
348 	    (void *)GTT_ADDR(agpmaster), (void *)MMIO_BASE(agpmaster)));
349 	return (0);
350 }
351 
352 /*
353  * Try to initialize agp master.
354  * 0 is returned if the device is successfully initialized. AGP master soft
355  * state is returned in master_softcp if needed.
356  * Otherwise -1 is returned and *master_softcp is set to NULL.
357  */
358 int
agpmaster_attach(dev_info_t * devi,agp_master_softc_t ** master_softcp,ddi_acc_handle_t pci_acc_hdl,minor_t minor)359 agpmaster_attach(dev_info_t *devi, agp_master_softc_t **master_softcp,
360     ddi_acc_handle_t pci_acc_hdl, minor_t minor)
361 {
362 	int instance;
363 	int status;
364 	agp_master_softc_t *agpmaster;
365 	char buf[80];
366 
367 
368 	ASSERT(pci_acc_hdl);
369 	*master_softcp = NULL;
370 	agpmaster = (agp_master_softc_t *)
371 	    kmem_zalloc(sizeof (agp_master_softc_t), KM_SLEEP);
372 
373 	agpmaster->agpm_id =
374 	    pci_config_get32(pci_acc_hdl, PCI_CONF_VENID);
375 	agpmaster->agpm_acc_hdl = pci_acc_hdl;
376 
377 	if (!detect_i8xx_device(agpmaster)) {
378 		/* Intel 8XX, 915, 945 and 965 series */
379 		if (set_gtt_mmio(devi, agpmaster, pci_acc_hdl) != 0)
380 			goto fail;
381 	} else if (detect_agp_devcice(agpmaster, pci_acc_hdl)) {
382 		/* non IGD or AGP devices, AMD64 gart */
383 		AGPM_DEBUG((CE_WARN,
384 		    "agpmaster_attach: neither IGD or AGP devices exists"));
385 		agpmaster_detach(&agpmaster);
386 		return (0);
387 	}
388 
389 	agpmaster->agpm_data.agpm_gtt.gtt_info.igd_devid =
390 	    agpmaster->agpm_id;
391 
392 	/* create minor node for IGD or AGP device */
393 	instance = ddi_get_instance(devi);
394 
395 	(void) sprintf(buf, "%s%d", AGPMASTER_NAME, instance);
396 	status = ddi_create_minor_node(devi, buf, S_IFCHR, minor,
397 	    DDI_NT_AGP_MASTER, 0);
398 
399 	if (status != DDI_SUCCESS) {
400 		AGPM_DEBUG((CE_WARN,
401 		    "agpmaster_attach: create agpmaster node failed"));
402 		goto fail;
403 	}
404 
405 	*master_softcp = agpmaster;
406 	return (0);
407 fail:
408 	agpmaster_detach(&agpmaster);
409 	return (-1);
410 }
411 
412 /*
413  * Currently, it handles ioctl requests related with agp master device for
414  * layered driver (agpgart) only.
415  */
416 /*ARGSUSED*/
417 int
agpmaster_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * cred,int * rval,agp_master_softc_t * softc)418 agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred,
419     int *rval, agp_master_softc_t *softc)
420 {
421 	uint32_t base;
422 	uint32_t addr;
423 	igd_gtt_seg_t seg;
424 	agp_info_t info;
425 	uint32_t value;
426 	off_t cap;
427 	uint32_t command;
428 	static char kernel_only[] =
429 	    "agpmaster_ioctl: %s is a kernel only ioctl";
430 
431 	CONFIRM(softc);
432 
433 	switch (cmd) {
434 	case DEVICE_DETECT:
435 		if (!(mode & FKIOCTL)) {
436 			AGPM_DEBUG((CE_CONT, kernel_only, "DEVICE_DETECT"));
437 			return (ENXIO);
438 		}
439 
440 		if (ddi_copyout(&softc->agpm_dev_type,
441 		    (void *)data, sizeof (int), mode))
442 			return (EFAULT);
443 		break;
444 
445 	case AGP_MASTER_SETCMD:
446 		if (!(mode & FKIOCTL)) {
447 			AGPM_DEBUG((CE_CONT, kernel_only, "AGP_MASTER_SETCMD"));
448 			return (ENXIO);
449 		}
450 
451 		CONFIRM(softc->agpm_dev_type == DEVICE_IS_AGP);
452 		CONFIRM(softc->agpm_data.agpm_acaptr);
453 
454 		if (ddi_copyin((void *)data, &command,
455 		    sizeof (uint32_t), mode))
456 			return (EFAULT);
457 
458 		pci_config_put32(softc->agpm_acc_hdl,
459 		    softc->agpm_data.agpm_acaptr + AGP_CONF_COMMAND,
460 		    command);
461 		break;
462 
463 	case AGP_MASTER_GETINFO:
464 		if (!(mode & FKIOCTL)) {
465 			AGPM_DEBUG((CE_CONT, kernel_only,
466 			    "AGP_MASTER_GETINFO"));
467 			return (ENXIO);
468 		}
469 
470 		CONFIRM(softc->agpm_dev_type == DEVICE_IS_AGP);
471 		CONFIRM(softc->agpm_data.agpm_acaptr);
472 
473 		cap = softc->agpm_data.agpm_acaptr;
474 		value = pci_config_get32(softc->agpm_acc_hdl, cap);
475 		info.agpi_version.agpv_major = (uint16_t)((value >> 20) & 0xf);
476 		info.agpi_version.agpv_minor = (uint16_t)((value >> 16) & 0xf);
477 		info.agpi_devid = softc->agpm_id;
478 		info.agpi_mode = pci_config_get32(
479 		    softc->agpm_acc_hdl, cap + AGP_CONF_STATUS);
480 
481 		if (ddi_copyout(&info, (void *)data,
482 		    sizeof (agp_info_t), mode))
483 			return (EFAULT);
484 		break;
485 
486 	case I810_SET_GTT_BASE:
487 		if (!(mode & FKIOCTL)) {
488 			AGPM_DEBUG((CE_CONT, kernel_only, "I810_SET_GTT_ADDR"));
489 			return (ENXIO);
490 		}
491 
492 		CONFIRM(softc->agpm_dev_type == DEVICE_IS_I810);
493 
494 		if (ddi_copyin((void *)data, &base, sizeof (uint32_t), mode))
495 			return (EFAULT);
496 
497 		/* enables page table */
498 		addr = (base & GTT_BASE_MASK) | GTT_TABLE_VALID;
499 
500 		AGPM_WRITE(softc, PGTBL_CTL, addr);
501 		break;
502 
503 	case I8XX_GET_INFO:
504 		if (!(mode & FKIOCTL)) {
505 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_GET_INFO"));
506 			return (ENXIO);
507 		}
508 
509 		CONFIRM(IS_IGD(softc));
510 
511 		if (ddi_copyout(&softc->agpm_data.agpm_gtt.gtt_info,
512 		    (void *)data, sizeof (igd_info_t), mode))
513 			return (EFAULT);
514 		break;
515 
516 	case I8XX_ADD2GTT:
517 		if (!(mode & FKIOCTL)) {
518 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_ADD2GTT"));
519 			return (ENXIO);
520 		}
521 
522 		CONFIRM(IS_IGD(softc));
523 
524 		if (ddi_copyin((void *)data, &seg,
525 		    sizeof (igd_gtt_seg_t), mode))
526 			return (EFAULT);
527 
528 		if (i8xx_add_to_gtt(&softc->agpm_data.agpm_gtt, seg))
529 			return (EINVAL);
530 		break;
531 
532 	case I8XX_REM_GTT:
533 		if (!(mode & FKIOCTL)) {
534 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_REM_GTT"));
535 			return (ENXIO);
536 		}
537 
538 		CONFIRM(IS_IGD(softc));
539 
540 		if (ddi_copyin((void *)data, &seg,
541 		    sizeof (igd_gtt_seg_t), mode))
542 			return (EFAULT);
543 
544 		i8xx_remove_from_gtt(&softc->agpm_data.agpm_gtt, seg);
545 		break;
546 
547 	case I8XX_RW_GTT:
548 		if (!(mode & FKIOCTL)) {
549 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_RW_GTT"));
550 			return (ENXIO);
551 		}
552 
553 		CONFIRM(IS_IGD(softc));
554 
555 		if (ddi_copyin((void *)data, &seg,
556 		    sizeof (igd_gtt_seg_t), mode))
557 			return (EFAULT);
558 
559 		/*
560 		 * Read or write based on flags set in
561 		 * ioctl_agpgart_rw_gtt()
562 		 * Used to save/restore GTT state.
563 		 */
564 		if (seg.igs_flags == 0) {
565 			if (i8xx_read_gtt(&softc->agpm_data.agpm_gtt, seg))
566 				return (EINVAL);
567 		} else {
568 			if (i8xx_write_gtt(&softc->agpm_data.agpm_gtt, seg))
569 				return (EINVAL);
570 		}
571 		break;
572 
573 	case I8XX_UNCONFIG:
574 		if (!(mode & FKIOCTL)) {
575 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_UNCONFIG"));
576 			return (ENXIO);
577 		}
578 
579 		CONFIRM(IS_IGD(softc));
580 
581 		if (softc->agpm_dev_type == DEVICE_IS_I810)
582 			AGPM_WRITE(softc, PGTBL_CTL, 0);
583 		/*
584 		 * may need to clear all gtt entries here for i830 series,
585 		 * but may not be necessary
586 		 */
587 		break;
588 	}
589 	return (0);
590 }
591 
592 /*
593  * If AGP cap pointer is successfully found, none-zero value is returned.
594  * Otherwise 0 is returned.
595  */
596 static off_t
agpmaster_cap_find(ddi_acc_handle_t acc_handle)597 agpmaster_cap_find(ddi_acc_handle_t acc_handle)
598 {
599 	off_t		nextcap;
600 	uint32_t	ncapid;
601 	uint8_t		value;
602 
603 	/* check if this device supports capibility pointer */
604 	value = (uint8_t)(pci_config_get16(acc_handle, PCI_CONF_STAT)
605 	    & PCI_CONF_CAP_MASK);
606 
607 	if (!value)
608 		return (0);
609 	/* get the offset of the first capability pointer from CAPPTR */
610 	nextcap = (off_t)(pci_config_get8(acc_handle, AGP_CONF_CAPPTR));
611 
612 	/* check AGP capability from the first capability pointer */
613 	while (nextcap) {
614 		ncapid = pci_config_get32(acc_handle, nextcap);
615 		if ((ncapid & PCI_CONF_CAPID_MASK)
616 		    == AGP_CAP_ID) /* find AGP cap */
617 			break;
618 
619 		nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8);
620 	}
621 
622 	return (nextcap);
623 
624 }
625 
626 /*
627  * If i8xx device is successfully detected, 0 is returned.
628  * Otherwise -1 is returned.
629  */
630 static int
detect_i8xx_device(agp_master_softc_t * master_softc)631 detect_i8xx_device(agp_master_softc_t *master_softc)
632 {
633 
634 	switch (master_softc->agpm_id) {
635 	case INTEL_IGD_810:
636 	case INTEL_IGD_810DC:
637 	case INTEL_IGD_810E:
638 	case INTEL_IGD_815:
639 		master_softc->agpm_dev_type = DEVICE_IS_I810;
640 		break;
641 	case INTEL_IGD_830M:
642 	case INTEL_IGD_845G:
643 	case INTEL_IGD_855GM:
644 	case INTEL_IGD_865G:
645 	case INTEL_IGD_915:
646 	case INTEL_IGD_915GM:
647 	case INTEL_IGD_945:
648 	case INTEL_IGD_945GM:
649 	case INTEL_IGD_945GME:
650 	case INTEL_IGD_946GZ:
651 	case INTEL_IGD_965G1:
652 	case INTEL_IGD_965G2:
653 	case INTEL_IGD_965GM:
654 	case INTEL_IGD_965GME:
655 	case INTEL_IGD_965Q:
656 	case INTEL_IGD_Q35:
657 	case INTEL_IGD_G33:
658 	case INTEL_IGD_Q33:
659 	case INTEL_IGD_GM45:
660 	case INTEL_IGD_EL:
661 	case INTEL_IGD_Q45:
662 	case INTEL_IGD_G45:
663 	case INTEL_IGD_G41:
664 	case INTEL_IGD_IGDNG_D:
665 	case INTEL_IGD_IGDNG_M:
666 	case INTEL_IGD_B43:
667 		/*
668 		 * Note: This module is not used for Intel Gen6 or later
669 		 * devices (Sandy Bridge etc.) so no need to add any
670 		 * PCI IDs here for those devices.
671 		 */
672 		master_softc->agpm_dev_type = DEVICE_IS_I830;
673 		break;
674 	default:		/* unknown id */
675 		AGPM_DEBUG((CE_CONT, "unknown i8xx_device 0x%x",
676 		    master_softc->agpm_id));
677 		return (-1);
678 	}
679 
680 	return (0);
681 }
682 
683 /*
684  * If agp master is successfully detected, 0 is returned.
685  * Otherwise -1 is returned.
686  */
687 static int
detect_agp_devcice(agp_master_softc_t * master_softc,ddi_acc_handle_t acc_handle)688 detect_agp_devcice(agp_master_softc_t *master_softc,
689     ddi_acc_handle_t acc_handle)
690 {
691 	off_t cap;
692 
693 	cap = agpmaster_cap_find(acc_handle);
694 	if (cap) {
695 		master_softc->agpm_dev_type = DEVICE_IS_AGP;
696 		master_softc->agpm_data.agpm_acaptr = cap;
697 		return (0);
698 	} else {
699 		return (-1);
700 	}
701 
702 }
703 
704 /*
705  * Please refer to GART and GTT entry format table in agpdefs.h for
706  * intel GTT entry format.
707  */
708 static int
phys2entry(uint32_t type,uint32_t physaddr,uint32_t * entry)709 phys2entry(uint32_t type, uint32_t physaddr, uint32_t *entry)
710 {
711 	uint32_t value;
712 
713 	switch (type) {
714 	case AGP_PHYSICAL:
715 	case AGP_NORMAL:
716 		value = (physaddr & GTT_PTE_MASK) | GTT_PTE_VALID;
717 		break;
718 	default:
719 		AGPM_DEBUG((CE_WARN, "phys2entry type %d", type));
720 		return (-1);
721 	}
722 
723 	*entry = value;
724 
725 	return (0);
726 }
727 
728 static int
i8xx_add_to_gtt(gtt_impl_t * gtt,igd_gtt_seg_t seg)729 i8xx_add_to_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg)
730 {
731 	int i;
732 	uint32_t *paddr;
733 	uint32_t entry;
734 	uint32_t maxpages;
735 
736 	maxpages = gtt->gtt_info.igd_apersize;
737 	maxpages = GTT_MB_TO_PAGES(maxpages);
738 
739 	/* check if gtt max page number is reached */
740 	if ((seg.igs_pgstart + seg.igs_npage) > maxpages)
741 		return (-1);
742 
743 	/*
744 	 * Note: Caller supplies a gtt address from which we
745 	 * extract a uint32_t gtt_pte_t to set in the GTT.
746 	 */
747 	paddr = seg.igs_phyaddr;
748 	for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage);
749 	    i++, paddr++) {
750 		if (phys2entry(seg.igs_type, *paddr, &entry))
751 			return (-1);
752 		ddi_put32(gtt->gtt_handle,
753 		    (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)),
754 		    entry);
755 	}
756 
757 	return (0);
758 }
759 
760 static void
i8xx_remove_from_gtt(gtt_impl_t * gtt,igd_gtt_seg_t seg)761 i8xx_remove_from_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg)
762 {
763 	int i;
764 	uint32_t maxpages;
765 	uint32_t entry;
766 
767 	maxpages = gtt->gtt_info.igd_apersize;
768 	maxpages = GTT_MB_TO_PAGES(maxpages);
769 
770 	/*
771 	 * If non-zero, seg.igs_scratch is the pfn_t for a
772 	 * "scratch" page to use instead of zero.
773 	 */
774 	if (seg.igs_scratch == 0 ||
775 	    phys2entry(seg.igs_type, seg.igs_scratch, &entry) != 0) {
776 		entry = 0;
777 	}
778 
779 	/* check if gtt max page number is reached */
780 	if ((seg.igs_pgstart + seg.igs_npage) > maxpages)
781 		return;
782 
783 	for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); i++) {
784 		ddi_put32(gtt->gtt_handle,
785 		    (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)),
786 		    entry);
787 	}
788 }
789 
790 /*
791  * Low-level read GTT
792  */
793 static int
i8xx_read_gtt(gtt_impl_t * gtt,igd_gtt_seg_t seg)794 i8xx_read_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg)
795 {
796 	int i;
797 	uint32_t *paddr;
798 	uint32_t maxpages;
799 
800 	maxpages = gtt->gtt_info.igd_apersize;
801 	maxpages = GTT_MB_TO_PAGES(maxpages);
802 
803 	/* Buffer into which we'll read. */
804 	paddr = seg.igs_phyaddr;
805 	if (paddr == NULL)
806 		return (-1);
807 
808 	/* check if gtt max page number is reached */
809 	if ((seg.igs_pgstart + seg.igs_npage) > maxpages)
810 		return (-1);
811 
812 	paddr = seg.igs_phyaddr;
813 	for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage);
814 	    i++, paddr++) {
815 		*paddr = ddi_get32(gtt->gtt_handle,
816 		    (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)));
817 	}
818 
819 	return (0);
820 }
821 
822 /*
823  * Low-level write GTT
824  */
825 static int
i8xx_write_gtt(gtt_impl_t * gtt,igd_gtt_seg_t seg)826 i8xx_write_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg)
827 {
828 	int i;
829 	uint32_t *paddr;
830 	uint32_t maxpages;
831 
832 	maxpages = gtt->gtt_info.igd_apersize;
833 	maxpages = GTT_MB_TO_PAGES(maxpages);
834 
835 	/* Buffer from which we'll write. */
836 	paddr = seg.igs_phyaddr;
837 	if (paddr == NULL)
838 		return (-1);
839 
840 	/* check if gtt max page number is reached */
841 	if ((seg.igs_pgstart + seg.igs_npage) > maxpages)
842 		return (-1);
843 
844 	paddr = seg.igs_phyaddr;
845 	for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage);
846 	    i++, paddr++) {
847 		ddi_put32(gtt->gtt_handle,
848 		    (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)),
849 		    *paddr);
850 	}
851 
852 	return (0);
853 }
854