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