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