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