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 ®_size); 2063446Smrj } else 2073446Smrj status = ddi_dev_regsize(devi, I8XX_FB_REGSET, 2083446Smrj ®_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