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