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