xref: /onnv-gate/usr/src/uts/intel/io/agpmaster/agpmaster.c (revision 4303:6dc328847ed0)
13446Smrj /*
23446Smrj  * CDDL HEADER START
33446Smrj  *
43446Smrj  * The contents of this file are subject to the terms of the
53446Smrj  * Common Development and Distribution License (the "License").
63446Smrj  * You may not use this file except in compliance with the License.
73446Smrj  *
83446Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93446Smrj  * or http://www.opensolaris.org/os/licensing.
103446Smrj  * See the License for the specific language governing permissions
113446Smrj  * and limitations under the License.
123446Smrj  *
133446Smrj  * When distributing Covered Code, include this CDDL HEADER in each
143446Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153446Smrj  * If applicable, add the following below this CDDL HEADER, with the
163446Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
173446Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
183446Smrj  *
193446Smrj  * CDDL HEADER END
203446Smrj  */
213446Smrj 
223446Smrj /*
23*4303Skz151634  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
243446Smrj  * Use is subject to license terms.
253446Smrj  */
263446Smrj 
273446Smrj #pragma ident	"%Z%%M%	%I%	%E% SMI"
283446Smrj 
293446Smrj /*
303446Smrj  * Misc module for AGP master device support
313446Smrj  */
323446Smrj 
333446Smrj #include <sys/modctl.h>
343446Smrj #include <sys/pci.h>
353446Smrj #include <sys/stat.h>
363446Smrj #include <sys/file.h>
373446Smrj #include <sys/types.h>
383446Smrj #include <sys/dditypes.h>
393446Smrj #include <sys/sunddi.h>
403446Smrj #include <sys/agpgart.h>
413446Smrj #include <sys/agp/agpdefs.h>
423446Smrj #include <sys/agp/agpmaster_io.h>
433446Smrj 
443446Smrj #define	I8XX_MMIO_REGSET	2
453446Smrj #define	I8XX_FB_REGSET		1
463446Smrj #define	I8XX_PTE_OFFSET		0x10000
473446Smrj #define	I8XX_PGTBL_CTL		0x2020
483446Smrj #define	I915_GTTADDR_BAR	4
493446Smrj #define	I915_FB_REGSET		3
503446Smrj 
513446Smrj #ifdef DEBUG
523446Smrj #define	CONFIRM(value) ASSERT(value)
533446Smrj #else
543446Smrj #define	CONFIRM(value) if (!(value)) return (EINVAL)
553446Smrj #endif
563446Smrj 
573446Smrj int agpm_debug = 0;
583446Smrj #define	AGPM_DEBUG(args)	if (agpm_debug >= 1) cmn_err args
593446Smrj 
603446Smrj /*
613446Smrj  * Whether it is a Intel integrated graphics card
623446Smrj  */
633446Smrj #define	IS_IGD(agpmaster) ((agpmaster->agpm_dev_type == DEVICE_IS_I810) || \
643446Smrj 		    (agpmaster->agpm_dev_type == DEVICE_IS_I830))
653446Smrj 
663446Smrj 
673446Smrj #define	IS_INTEL_9XX(agpmaster) ((agpmaster->agpm_id == INTEL_IGD_910) || \
683446Smrj 		    (agpmaster->agpm_id == INTEL_IGD_910M) || \
69*4303Skz151634 		    (agpmaster->agpm_id == INTEL_IGD_945) || \
70*4303Skz151634 		    (agpmaster->agpm_id == INTEL_IGD_945GM))
713446Smrj 
723446Smrj static struct modlmisc modlmisc = {
733446Smrj 	&mod_miscops, "AGP master interfaces v%I%"
743446Smrj };
753446Smrj 
763446Smrj static struct modlinkage modlinkage = {
773446Smrj 	MODREV_1, (void *)&modlmisc, NULL
783446Smrj };
793446Smrj 
803446Smrj static ddi_device_acc_attr_t i8xx_dev_access = {
813446Smrj 	DDI_DEVICE_ATTR_V0,
823446Smrj 	DDI_NEVERSWAP_ACC,
833446Smrj 	DDI_STRICTORDER_ACC
843446Smrj };
853446Smrj 
863446Smrj static off_t agpmaster_cap_find(ddi_acc_handle_t);
873446Smrj static int detect_i8xx_device(agp_master_softc_t *);
883446Smrj static int detect_agp_devcice(agp_master_softc_t *, ddi_acc_handle_t);
893446Smrj static int i8xx_add_to_gtt(gtt_impl_t *, igd_gtt_seg_t);
903446Smrj static void i8xx_remove_from_gtt(gtt_impl_t *, igd_gtt_seg_t);
913446Smrj 
923446Smrj int
933446Smrj _init(void)
943446Smrj {
953446Smrj 	int	err;
963446Smrj 
973446Smrj 	if ((err = mod_install(&modlinkage)) != 0)
983446Smrj 		return (err);
993446Smrj 
1003446Smrj 	return (0);
1013446Smrj }
1023446Smrj 
1033446Smrj int
1043446Smrj _fini(void)
1053446Smrj {
1063446Smrj 	int	err;
1073446Smrj 
1083446Smrj 	if ((err = mod_remove(&modlinkage)) != 0)
1093446Smrj 		return (err);
1103446Smrj 
1113446Smrj 	return (0);
1123446Smrj }
1133446Smrj 
1143446Smrj int
1153446Smrj _info(struct modinfo *modinfop)
1163446Smrj {
1173446Smrj 	return (mod_info(&modlinkage, modinfop));
1183446Smrj }
1193446Smrj 
1203446Smrj /*
1213446Smrj  * Minor node is not removed here, since the caller (xx_attach) is
1223446Smrj  * responsible for removing all nodes.
1233446Smrj  */
1243446Smrj void
1253446Smrj agpmaster_detach(agp_master_softc_t **master_softcp)
1263446Smrj {
1273446Smrj 	agp_master_softc_t *master_softc;
1283446Smrj 
1293446Smrj 	ASSERT(master_softcp);
1303446Smrj 	master_softc = *master_softcp;
1313446Smrj 
1323446Smrj 	/* intel integrated device */
1333446Smrj 	if (IS_IGD(master_softc)) {
1343446Smrj 		if (master_softc->agpm_data.agpm_gtt.gtt_mmio_handle != NULL) {
1353446Smrj 			ddi_regs_map_free(
1363446Smrj 			    &master_softc->agpm_data.agpm_gtt.gtt_mmio_handle);
1373446Smrj 		}
1383446Smrj 	}
1393446Smrj 
1403446Smrj 	kmem_free(master_softc, sizeof (agp_master_softc_t));
1413446Smrj 	master_softc = NULL;
1423446Smrj 
1433446Smrj 	return;
1443446Smrj 
1453446Smrj }
1463446Smrj 
1473446Smrj /*
1483446Smrj  * Try to initialize agp master.
1493446Smrj  * 0 is returned if the device is successfully initialized. AGP master soft
1503446Smrj  * state is returned in master_softcp if needed.
1513446Smrj  * Otherwise -1 is returned and *master_softcp is set to NULL.
1523446Smrj  */
1533446Smrj int
1543446Smrj agpmaster_attach(dev_info_t *devi, agp_master_softc_t **master_softcp,
1553446Smrj     ddi_acc_handle_t pci_acc_hdl, minor_t minor)
1563446Smrj {
1573446Smrj 	int instance;
1583446Smrj 	int status;
1593446Smrj 	agp_master_softc_t *agpmaster;
1603446Smrj 	uint32_t value;
1613446Smrj 	off_t reg_size;
1623446Smrj 	char buf[80];
1633446Smrj 
1643446Smrj 
1653446Smrj 	ASSERT(pci_acc_hdl);
1663446Smrj 	*master_softcp = NULL;
1673446Smrj 	agpmaster = (agp_master_softc_t *)
1683446Smrj 	    kmem_zalloc(sizeof (agp_master_softc_t), KM_SLEEP);
1693446Smrj 
1703446Smrj 	agpmaster->agpm_id =
1713446Smrj 	    pci_config_get32(pci_acc_hdl, PCI_CONF_VENID);
1723446Smrj 	agpmaster->agpm_acc_hdl = pci_acc_hdl;
1733446Smrj 
1743446Smrj 	if (!detect_i8xx_device(agpmaster)) {
1753446Smrj 		/* map mmio register set */
1763446Smrj 		if (IS_INTEL_9XX(agpmaster)) {
1773446Smrj 			status = ddi_regs_map_setup(devi, I915_GTTADDR_BAR,
1783446Smrj 			    &agpmaster->agpm_data.agpm_gtt.gtt_mmio_base,
1793446Smrj 			    0, 0, &i8xx_dev_access,
1803446Smrj 			    &agpmaster->agpm_data.agpm_gtt.gtt_mmio_handle);
1813446Smrj 		} else {
1823446Smrj 			status = ddi_regs_map_setup(devi, I8XX_MMIO_REGSET,
1833446Smrj 			    &agpmaster->agpm_data.agpm_gtt.gtt_mmio_base,
1843446Smrj 			    0, 0, &i8xx_dev_access,
1853446Smrj 			    &agpmaster->agpm_data.agpm_gtt.gtt_mmio_handle);
1863446Smrj 		}
1873446Smrj 
1883446Smrj 		if (status != DDI_SUCCESS) {
1893446Smrj 			AGPM_DEBUG((CE_WARN,
1903446Smrj 			    "agpmaster_attach: ddi_regs_map_setup failed"));
1913446Smrj 			goto fail;
1923446Smrj 		}
1933446Smrj 		/* get GTT range base offset */
1943446Smrj 		if (IS_INTEL_9XX(agpmaster)) {
1953446Smrj 			agpmaster->agpm_data.agpm_gtt.gtt_addr =
1963446Smrj 			    agpmaster->agpm_data.agpm_gtt.gtt_mmio_base;
1973446Smrj 		} else
1983446Smrj 			agpmaster->agpm_data.agpm_gtt.gtt_addr =
199*4303Skz151634 			    agpmaster->agpm_data.agpm_gtt.gtt_mmio_base +
200*4303Skz151634 			    I8XX_PTE_OFFSET;
2013446Smrj 
2023446Smrj 		/* get graphics memory size */
2033446Smrj 		if (IS_INTEL_9XX(agpmaster)) {
2043446Smrj 			status = ddi_dev_regsize(devi, I915_FB_REGSET,
2053446Smrj 			    &reg_size);
2063446Smrj 		} else
2073446Smrj 			status = ddi_dev_regsize(devi, I8XX_FB_REGSET,
2083446Smrj 			    &reg_size);
2093446Smrj 		/*
2103446Smrj 		 * if memory size is smaller than a certain value, it means
2113446Smrj 		 * the register set number for graphics memory range might
2123446Smrj 		 * be wrong
2133446Smrj 		 */
2143446Smrj 		if (status != DDI_SUCCESS || reg_size < 0x400000) {
2153446Smrj 			AGPM_DEBUG((CE_WARN,
2163446Smrj 			    "agpmaster_attach: ddi_dev_regsize error"));
2173446Smrj 			goto fail;
2183446Smrj 		}
2193446Smrj 
2203446Smrj 		agpmaster->agpm_data.agpm_gtt.gtt_info.igd_apersize =
2213446Smrj 		    BYTES2MB(reg_size);
2223446Smrj 		if (IS_INTEL_9XX(agpmaster)) {
2233446Smrj 			value = pci_config_get32(pci_acc_hdl,
2243446Smrj 			    I915_CONF_GMADR);
2253446Smrj 		} else
2263446Smrj 			value = pci_config_get32(pci_acc_hdl,
2273446Smrj 			    I8XX_CONF_GMADR);
2283446Smrj 
2293446Smrj 		agpmaster->agpm_data.agpm_gtt.gtt_info.igd_aperbase =
2303446Smrj 		    value & GTT_BASE_MASK;
2313446Smrj 		agpmaster->agpm_data.agpm_gtt.gtt_info.igd_devid =
2323446Smrj 		    agpmaster->agpm_id;
2333446Smrj 	} else if (detect_agp_devcice(agpmaster, pci_acc_hdl)) {
2343446Smrj 		/*
2353446Smrj 		 * non IGD or AGP devices, AMD64 gart
2363446Smrj 		 */
2373446Smrj 		AGPM_DEBUG((CE_WARN,
2383446Smrj 		    "agpmaster_attach: neither IGD or AGP devices exists"));
2393446Smrj 		agpmaster_detach(&agpmaster);
2403446Smrj 		return (0);
2413446Smrj 	}
2423446Smrj 
2433446Smrj 	/* create minor node for IGD or AGP device */
2443446Smrj 	instance = ddi_get_instance(devi);
2453446Smrj 
2463446Smrj 	(void) sprintf(buf, "%s%d", AGPMASTER_NAME, instance);
2473446Smrj 	status = ddi_create_minor_node(devi, buf, S_IFCHR, minor,
2483446Smrj 	    DDI_NT_AGP_MASTER, 0);
2493446Smrj 
2503446Smrj 	if (status != DDI_SUCCESS) {
2513446Smrj 		AGPM_DEBUG((CE_WARN,
2523446Smrj 		    "agpmaster_attach: create agpmaster node failed"));
2533446Smrj 		goto fail;
2543446Smrj 	}
2553446Smrj 
2563446Smrj 	*master_softcp = agpmaster;
2573446Smrj 	return (0);
2583446Smrj fail:
2593446Smrj 	agpmaster_detach(&agpmaster);
2603446Smrj 	return (-1);
2613446Smrj }
2623446Smrj 
2633446Smrj /*
2643446Smrj  * Currently, it handles ioctl requests related with agp master device for
2653446Smrj  * layered driver (agpgart) only.
2663446Smrj  */
2673446Smrj /*ARGSUSED*/
2683446Smrj int
2693446Smrj agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred,
2703446Smrj     int *rval, agp_master_softc_t *softc)
2713446Smrj {
2723446Smrj 	uint32_t base;
2733446Smrj 	uint32_t addr;
2743446Smrj 	igd_gtt_seg_t seg;
2753446Smrj 	agp_info_t info;
2763446Smrj 	uint32_t value;
2773446Smrj 	off_t cap;
2783446Smrj 	uint32_t command;
2793446Smrj 	static char kernel_only[] =
2803446Smrj 	    "agpmaster_ioctl: %s is a kernel only ioctl";
2813446Smrj 
2823446Smrj 	CONFIRM(softc);
2833446Smrj 
2843446Smrj 	switch (cmd) {
2853446Smrj 	case DEVICE_DETECT:
2863446Smrj 		if (!(mode & FKIOCTL)) {
2873446Smrj 			AGPM_DEBUG((CE_CONT, kernel_only, "DEVICE_DETECT"));
2883446Smrj 			return (ENXIO);
2893446Smrj 		}
2903446Smrj 
2913446Smrj 		if (ddi_copyout(&softc->agpm_dev_type,
2923446Smrj 		    (void *)data, sizeof (int), mode))
2933446Smrj 			return (EFAULT);
2943446Smrj 		break;
2953446Smrj 	case AGP_MASTER_SETCMD:
2963446Smrj 		if (!(mode & FKIOCTL)) {
2973446Smrj 			AGPM_DEBUG((CE_CONT, kernel_only, "AGP_MASTER_SETCMD"));
2983446Smrj 			return (ENXIO);
2993446Smrj 		}
3003446Smrj 
3013446Smrj 		CONFIRM(softc->agpm_dev_type == DEVICE_IS_AGP);
3023446Smrj 		CONFIRM(softc->agpm_data.agpm_acaptr);
3033446Smrj 
3043446Smrj 		if (ddi_copyin((void *)data, &command,
3053446Smrj 		    sizeof (uint32_t), mode))
3063446Smrj 			return (EFAULT);
3073446Smrj 
3083446Smrj 		pci_config_put32(softc->agpm_acc_hdl,
3093446Smrj 		    softc->agpm_data.agpm_acaptr + AGP_CONF_COMMAND,
3103446Smrj 		    command);
3113446Smrj 		break;
3123446Smrj 	case AGP_MASTER_GETINFO:
3133446Smrj 		if (!(mode & FKIOCTL)) {
3143446Smrj 			AGPM_DEBUG((CE_CONT, kernel_only,
3153446Smrj 			    "AGP_MASTER_GETINFO"));
3163446Smrj 			return (ENXIO);
3173446Smrj 		}
3183446Smrj 
3193446Smrj 		CONFIRM(softc->agpm_dev_type == DEVICE_IS_AGP);
3203446Smrj 		CONFIRM(softc->agpm_data.agpm_acaptr);
3213446Smrj 
3223446Smrj 		cap = softc->agpm_data.agpm_acaptr;
3233446Smrj 		value = pci_config_get32(softc->agpm_acc_hdl, cap);
3243446Smrj 		info.agpi_version.agpv_major = (uint16_t)((value >> 20) & 0xf);
3253446Smrj 		info.agpi_version.agpv_minor = (uint16_t)((value >> 16) & 0xf);
3263446Smrj 		info.agpi_devid = softc->agpm_id;
3273446Smrj 		info.agpi_mode = pci_config_get32(
3283446Smrj 		    softc->agpm_acc_hdl, cap + AGP_CONF_STATUS);
3293446Smrj 
3303446Smrj 		if (ddi_copyout(&info, (void *)data,
3313446Smrj 		    sizeof (agp_info_t), mode))
3323446Smrj 			return (EFAULT);
3333446Smrj 		break;
3343446Smrj 	case I810_SET_GTT_BASE:
3353446Smrj 		if (!(mode & FKIOCTL)) {
3363446Smrj 			AGPM_DEBUG((CE_CONT, kernel_only, "I810_SET_GTT_ADDR"));
3373446Smrj 			return (ENXIO);
3383446Smrj 		}
3393446Smrj 
3403446Smrj 		CONFIRM(softc->agpm_dev_type == DEVICE_IS_I810);
3413446Smrj 
3423446Smrj 		if (ddi_copyin((void *)data, &base, sizeof (uint32_t), mode))
3433446Smrj 			return (EFAULT);
3443446Smrj 
3453446Smrj 		/* enables page table */
3463446Smrj 		addr = (base & GTT_BASE_MASK) | GTT_TABLE_VALID;
3473446Smrj 
3483446Smrj 		ddi_put32(softc->agpm_data.agpm_gtt.gtt_mmio_handle,
3493446Smrj 		    (uint32_t *)(softc->agpm_data.agpm_gtt.gtt_mmio_base +
350*4303Skz151634 		    I8XX_PGTBL_CTL),
3513446Smrj 		    addr);
3523446Smrj 		break;
3533446Smrj 	case I8XX_GET_INFO:
3543446Smrj 		if (!(mode & FKIOCTL)) {
3553446Smrj 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_GET_INFO"));
3563446Smrj 			return (ENXIO);
3573446Smrj 		}
3583446Smrj 
3593446Smrj 		CONFIRM(IS_IGD(softc));
3603446Smrj 
3613446Smrj 		if (ddi_copyout(&softc->agpm_data.agpm_gtt.gtt_info,
3623446Smrj 		    (void *)data, sizeof (igd_info_t), mode))
3633446Smrj 			return (EFAULT);
3643446Smrj 		break;
3653446Smrj 	case I8XX_ADD2GTT:
3663446Smrj 		if (!(mode & FKIOCTL)) {
3673446Smrj 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_ADD2GTT"));
3683446Smrj 			return (ENXIO);
3693446Smrj 		}
3703446Smrj 
3713446Smrj 		CONFIRM(IS_IGD(softc));
3723446Smrj 
3733446Smrj 		if (ddi_copyin((void *)data, &seg,
3743446Smrj 		    sizeof (igd_gtt_seg_t), mode))
3753446Smrj 			return (EFAULT);
3763446Smrj 
3773446Smrj 		if (i8xx_add_to_gtt(&softc->agpm_data.agpm_gtt, seg))
3783446Smrj 			return (EINVAL);
3793446Smrj 		break;
3803446Smrj 	case I8XX_REM_GTT:
3813446Smrj 		if (!(mode & FKIOCTL)) {
3823446Smrj 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_REM_GTT"));
3833446Smrj 			return (ENXIO);
3843446Smrj 		}
3853446Smrj 
3863446Smrj 		CONFIRM(IS_IGD(softc));
3873446Smrj 
3883446Smrj 		if (ddi_copyin((void *)data, &seg,
3893446Smrj 		    sizeof (igd_gtt_seg_t), mode))
3903446Smrj 			return (EFAULT);
3913446Smrj 
3923446Smrj 		i8xx_remove_from_gtt(&softc->agpm_data.agpm_gtt, seg);
3933446Smrj 		break;
3943446Smrj 	case I8XX_UNCONFIG:
3953446Smrj 		if (!(mode & FKIOCTL)) {
3963446Smrj 			AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_UNCONFIG"));
3973446Smrj 			return (ENXIO);
3983446Smrj 		}
3993446Smrj 
4003446Smrj 		CONFIRM(IS_IGD(softc));
4013446Smrj 
4023446Smrj 		if (softc->agpm_dev_type == DEVICE_IS_I810)
4033446Smrj 			ddi_put32(softc->agpm_data.agpm_gtt.gtt_mmio_handle,
4043446Smrj 			    (uint32_t *)
4053446Smrj 			    (softc->agpm_data.agpm_gtt.gtt_mmio_base +
406*4303Skz151634 			    I8XX_PGTBL_CTL), 0);
4073446Smrj 		/*
4083446Smrj 		 * may need to clear all gtt entries here for i830 series,
4093446Smrj 		 * but may not be necessary
4103446Smrj 		 */
4113446Smrj 		break;
4123446Smrj 	}
4133446Smrj 	return (0);
4143446Smrj }
4153446Smrj 
4163446Smrj /*
4173446Smrj  * If AGP cap pointer is successfully found, none-zero value is returned.
4183446Smrj  * Otherwise 0 is returned.
4193446Smrj  */
4203446Smrj static off_t
4213446Smrj agpmaster_cap_find(ddi_acc_handle_t acc_handle)
4223446Smrj {
4233446Smrj 	off_t		nextcap;
4243446Smrj 	uint32_t	ncapid;
4253446Smrj 	uint8_t		value;
4263446Smrj 
4273446Smrj 	/* check if this device supports capibility pointer */
4283446Smrj 	value = (uint8_t)(pci_config_get16(acc_handle, PCI_CONF_STAT)
429*4303Skz151634 	    & PCI_CONF_CAP_MASK);
4303446Smrj 
4313446Smrj 	if (!value)
4323446Smrj 		return (0);
4333446Smrj 	/* get the offset of the first capability pointer from CAPPTR */
4343446Smrj 	nextcap = (off_t)(pci_config_get8(acc_handle, AGP_CONF_CAPPTR));
4353446Smrj 
4363446Smrj 	/* check AGP capability from the first capability pointer */
4373446Smrj 	while (nextcap) {
4383446Smrj 		ncapid = pci_config_get32(acc_handle, nextcap);
4393446Smrj 		if ((ncapid & PCI_CONF_CAPID_MASK)
4403446Smrj 		    == AGP_CAP_ID) /* find AGP cap */
4413446Smrj 			break;
4423446Smrj 
4433446Smrj 		nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8);
4443446Smrj 	}
4453446Smrj 
4463446Smrj 	return (nextcap);
4473446Smrj 
4483446Smrj }
4493446Smrj 
4503446Smrj /*
4513446Smrj  * If i8xx device is successfully detected, 0 is returned.
4523446Smrj  * Otherwise -1 is returned.
4533446Smrj  */
4543446Smrj static int
4553446Smrj detect_i8xx_device(agp_master_softc_t *master_softc)
4563446Smrj {
4573446Smrj 
4583446Smrj 	switch (master_softc->agpm_id) {
4593446Smrj 	case INTEL_IGD_810:
4603446Smrj 	case INTEL_IGD_810DC:
4613446Smrj 	case INTEL_IGD_810E:
4623446Smrj 	case INTEL_IGD_815:
4633446Smrj 		master_softc->agpm_dev_type = DEVICE_IS_I810;
4643446Smrj 		break;
4653446Smrj 	case INTEL_IGD_830M:
4663446Smrj 	case INTEL_IGD_845G:
4673446Smrj 	case INTEL_IGD_855GM:
4683446Smrj 	case INTEL_IGD_865G:
4693446Smrj 	case INTEL_IGD_910:
4703446Smrj 	case INTEL_IGD_910M:
4713446Smrj 	case INTEL_IGD_945:
472*4303Skz151634 	case INTEL_IGD_945GM:
4733446Smrj 		master_softc->agpm_dev_type = DEVICE_IS_I830;
4743446Smrj 		break;
4753446Smrj 	default:		/* unknown id */
4763446Smrj 		return (-1);
4773446Smrj 	}
4783446Smrj 
4793446Smrj 	return (0);
4803446Smrj }
4813446Smrj 
4823446Smrj /*
4833446Smrj  * If agp master is succssfully detected, 0 is returned.
4843446Smrj  * Otherwise -1 is returned.
4853446Smrj  */
4863446Smrj static int
4873446Smrj detect_agp_devcice(agp_master_softc_t *master_softc,
4883446Smrj     ddi_acc_handle_t acc_handle)
4893446Smrj {
4903446Smrj 	off_t cap;
4913446Smrj 
4923446Smrj 	cap = agpmaster_cap_find(acc_handle);
4933446Smrj 	if (cap) {
4943446Smrj 		master_softc->agpm_dev_type = DEVICE_IS_AGP;
4953446Smrj 		master_softc->agpm_data.agpm_acaptr = cap;
4963446Smrj 		return (0);
4973446Smrj 	} else {
4983446Smrj 		return (-1);
4993446Smrj 	}
5003446Smrj 
5013446Smrj }
5023446Smrj 
5033446Smrj /*
5043446Smrj  * Please refer to GART and GTT entry format table in agpdefs.h for
5053446Smrj  * intel GTT entry format.
5063446Smrj  */
5073446Smrj static int
5083446Smrj phys2entry(uint32_t type, uint32_t physaddr, uint32_t *entry)
5093446Smrj {
5103446Smrj 	uint32_t value;
5113446Smrj 
5123446Smrj 	switch (type) {
5133446Smrj 	case AGP_PHYSICAL:
5143446Smrj 	case AGP_NORMAL:
5153446Smrj 		value = (physaddr & GTT_PTE_MASK) | GTT_PTE_VALID;
5163446Smrj 		break;
5173446Smrj 	default:
5183446Smrj 		return (-1);
5193446Smrj 	}
5203446Smrj 
5213446Smrj 	*entry = value;
5223446Smrj 
5233446Smrj 	return (0);
5243446Smrj }
5253446Smrj 
5263446Smrj static int
5273446Smrj i8xx_add_to_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg)
5283446Smrj {
5293446Smrj 	int i;
5303446Smrj 	uint32_t *paddr;
5313446Smrj 	uint32_t entry;
5323446Smrj 	uint32_t maxpages;
5333446Smrj 
5343446Smrj 	maxpages = gtt->gtt_info.igd_apersize;
5353446Smrj 	maxpages = GTT_MB_TO_PAGES(maxpages);
5363446Smrj 
5373446Smrj 	paddr = seg.igs_phyaddr;
5383446Smrj 
5393446Smrj 	/* check if gtt max page number is reached */
5403446Smrj 	if ((seg.igs_pgstart + seg.igs_npage) > maxpages)
5413446Smrj 		return (-1);
5423446Smrj 
5433446Smrj 	paddr = seg.igs_phyaddr;
5443446Smrj 	for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage);
5453446Smrj 	    i++, paddr++) {
5463446Smrj 		if (phys2entry(seg.igs_type, *paddr, &entry))
5473446Smrj 			return (-1);
5483446Smrj 		ddi_put32(gtt->gtt_mmio_handle,
5493446Smrj 		    (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)),
5503446Smrj 		    entry);
5513446Smrj 	}
5523446Smrj 
5533446Smrj 	return (0);
5543446Smrj }
5553446Smrj 
5563446Smrj static void
5573446Smrj i8xx_remove_from_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg)
5583446Smrj {
5593446Smrj 	int i;
5603446Smrj 	uint32_t maxpages;
5613446Smrj 
5623446Smrj 	maxpages = gtt->gtt_info.igd_apersize;
5633446Smrj 	maxpages = GTT_MB_TO_PAGES(maxpages);
5643446Smrj 
5653446Smrj 	/* check if gtt max page number is reached */
5663446Smrj 	if ((seg.igs_pgstart + seg.igs_npage) > maxpages)
5673446Smrj 		return;
5683446Smrj 
5693446Smrj 	for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); i++) {
5703446Smrj 		ddi_put32(gtt->gtt_mmio_handle,
5713446Smrj 		    (uint32_t *)(gtt->gtt_addr +
5723446Smrj 		    i * sizeof (uint32_t)),
5733446Smrj 		    0);
5743446Smrj 	}
5753446Smrj }
576