1*4478Skz151634 /* 2*4478Skz151634 * CDDL HEADER START 3*4478Skz151634 * 4*4478Skz151634 * The contents of this file are subject to the terms of the 5*4478Skz151634 * Common Development and Distribution License (the "License"). 6*4478Skz151634 * You may not use this file except in compliance with the License. 7*4478Skz151634 * 8*4478Skz151634 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4478Skz151634 * or http://www.opensolaris.org/os/licensing. 10*4478Skz151634 * See the License for the specific language governing permissions 11*4478Skz151634 * and limitations under the License. 12*4478Skz151634 * 13*4478Skz151634 * When distributing Covered Code, include this CDDL HEADER in each 14*4478Skz151634 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4478Skz151634 * If applicable, add the following below this CDDL HEADER, with the 16*4478Skz151634 * fields enclosed by brackets "[]" replaced with your own identifying 17*4478Skz151634 * information: Portions Copyright [yyyy] [name of copyright owner] 18*4478Skz151634 * 19*4478Skz151634 * CDDL HEADER END 20*4478Skz151634 */ 21*4478Skz151634 223446Smrj /* 233527Sms148562 * 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 #include <sys/systm.h> 303446Smrj #include <sys/conf.h> 313446Smrj #include <sys/modctl.h> 323446Smrj #include <sys/file.h> 333446Smrj #include <sys/stat.h> 343446Smrj #include <sys/ddi.h> 353446Smrj #include <sys/sunddi.h> 363446Smrj #include <sys/modctl.h> 373446Smrj #include <sys/sunldi.h> 383446Smrj #include <sys/pci.h> 393446Smrj #include <sys/agpgart.h> 403446Smrj #include <sys/agp/agpdefs.h> 413446Smrj #include <sys/agp/agptarget_io.h> 423446Smrj 433446Smrj int agptarget_debug_var = 0; 443446Smrj #define TARGETDB_PRINT2(fmt) if (agptarget_debug_var >= 1) cmn_err fmt 453446Smrj #define INST2NODENUM(inst) (inst) 463446Smrj #define DEV2INST(dev) (getminor(dev)) 473446Smrj 483446Smrj typedef struct agp_target_softstate { 493446Smrj dev_info_t *tsoft_dip; 503446Smrj ddi_acc_handle_t tsoft_pcihdl; 513446Smrj uint32_t tsoft_devid; 523446Smrj /* The offset of the ACAPID register */ 533446Smrj off_t tsoft_acaptr; 543446Smrj kmutex_t tsoft_lock; 553446Smrj }agp_target_softstate_t; 563446Smrj 573446Smrj static void *agptarget_glob_soft_handle; 583446Smrj 593446Smrj #define GETSOFTC(instance) ((agp_target_softstate_t *) \ 603446Smrj ddi_get_soft_state(agptarget_glob_soft_handle, instance)); 613446Smrj 623446Smrj /* 633446Smrj * The AMD8151 bridge is the only supported 64 bit hardware 643446Smrj */ 653446Smrj static int 663446Smrj is_64bit_aper(agp_target_softstate_t *softstate) 673446Smrj { 683446Smrj return (softstate->tsoft_devid == AMD_BR_8151); 693446Smrj } 703446Smrj 713446Smrj /* 723446Smrj * agp_target_cap_find() 733446Smrj * 743446Smrj * Description: 753446Smrj * This function searches the linked capability list to find the offset 763446Smrj * of the AGP capability register. When it was not found, return 0. 773446Smrj * This works for standard AGP chipsets, but not for some Intel chipsets, 783446Smrj * like the I830M/I830MP/I852PM/I852GME/I855GME. It will return 0 for 793446Smrj * these chipsets even if AGP is supported. So the offset of acapid 803446Smrj * should be set manually in thoses cases. 813446Smrj * 823446Smrj * Arguments: 833446Smrj * pci_handle ddi acc handle of pci config 843446Smrj * 853446Smrj * Returns: 863446Smrj * 0 No capability pointer register found 873446Smrj * nexcap The AGP capability pointer register offset 883446Smrj */ 893446Smrj static off_t 903446Smrj agp_target_cap_find(ddi_acc_handle_t pci_handle) 913446Smrj { 923446Smrj off_t nextcap = 0; 933446Smrj uint32_t ncapid = 0; 943446Smrj uint8_t value = 0; 953446Smrj 963446Smrj /* Check if this device supports the capability pointer */ 973446Smrj value = (uint8_t)(pci_config_get16(pci_handle, PCI_CONF_STAT) 983446Smrj & PCI_CONF_CAP_MASK); 993446Smrj 1003446Smrj if (!value) 1013446Smrj return (0); 1023446Smrj /* Get the offset of the first capability pointer from CAPPTR */ 1033446Smrj nextcap = (off_t)(pci_config_get8(pci_handle, AGP_CONF_CAPPTR)); 1043446Smrj 1053446Smrj /* Check the AGP capability from the first capability pointer */ 1063446Smrj while (nextcap) { 1073446Smrj ncapid = pci_config_get32(pci_handle, nextcap); 1083446Smrj /* 1093446Smrj * AGP3.0 rev1.0 127 the capid was assigned by the PCI SIG, 1103446Smrj * 845 data sheet page 69 1113446Smrj */ 1123446Smrj if ((ncapid & PCI_CONF_CAPID_MASK) == 1133446Smrj AGP_CAP_ID) /* The AGP cap was found */ 1143446Smrj break; 1153446Smrj 1163446Smrj nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8); 1173446Smrj } 1183446Smrj 1193446Smrj return (nextcap); 1203446Smrj 1213446Smrj } 1223446Smrj 1233446Smrj /* 1243446Smrj * agp_target_get_aperbase() 1253446Smrj * 1263446Smrj * Description: 1273446Smrj * This function gets the AGP aperture base address from the AGP target 1283446Smrj * register, the AGP aperture base register was programmed by the BIOS. 1293446Smrj * 1303446Smrj * Arguments: 1313446Smrj * softstate driver soft state pointer 1323446Smrj * 1333446Smrj * Returns: 1343446Smrj * aper_base AGP aperture base address 1353446Smrj * 1363446Smrj * Notes: 1373446Smrj * If a 64bit bridge device is available, the AGP aperture base address 1383446Smrj * can be 64 bit. 1393446Smrj */ 1403446Smrj static uint64_t 1413446Smrj agp_target_get_apbase(agp_target_softstate_t *softstate) 1423446Smrj { 1433446Smrj uint64_t aper_base; 1443446Smrj 1453446Smrj if (!is_64bit_aper(softstate)) { 1463446Smrj aper_base = pci_config_get32(softstate->tsoft_pcihdl, 1473446Smrj AGP_CONF_APERBASE) & AGP_32_APERBASE_MASK; 1483446Smrj } else { 1493446Smrj aper_base = pci_config_get64(softstate->tsoft_pcihdl, 1503446Smrj AGP_CONF_APERBASE); 1513446Smrj /* 32-bit or 64-bit aperbase base pointer */ 1523446Smrj if ((aper_base & AGP_APER_TYPE_MASK) == 0) 1533446Smrj aper_base &= AGP_32_APERBASE_MASK; 1543446Smrj else 1553446Smrj aper_base &= AGP_64_APERBASE_MASK; 1563446Smrj } 1573446Smrj return (aper_base); 1583446Smrj } 1593446Smrj 1603446Smrj /* 1613446Smrj * agp_target_get_apsize() 1623446Smrj * 1633446Smrj * Description: 1643446Smrj * This function gets the AGP aperture size by reading the AGP aperture 1653446Smrj * size register. 1663446Smrj * Arguments: 1673446Smrj * softstate driver soft state pointer 1683446Smrj * 1693446Smrj * Return: 1703446Smrj * size The AGP aperture size in megabytes 1713446Smrj * 0 an unexpected error 1723446Smrj */ 1733446Smrj static size_t 1743446Smrj agp_target_get_apsize(agp_target_softstate_t *softstate) 1753446Smrj { 1763446Smrj off_t cap; 1773446Smrj uint16_t value; 1783446Smrj size_t size, regsize; 1793446Smrj 1803446Smrj ASSERT(softstate->tsoft_acaptr); 1813446Smrj cap = softstate->tsoft_acaptr; 1823446Smrj 1833446Smrj if ((softstate->tsoft_devid & VENDOR_ID_MASK) == INTEL_VENDOR_ID) { 1843446Smrj /* extend this value to 16 bit for later tests */ 1853446Smrj value = (uint16_t)pci_config_get8(softstate->tsoft_pcihdl, 1863446Smrj cap + AGP_CONF_APERSIZE) | AGP_APER_SIZE_MASK; 1873446Smrj } else { 1883446Smrj value = pci_config_get16(softstate->tsoft_pcihdl, 1893446Smrj cap + AGP_CONF_APERSIZE); 1903446Smrj } 1913446Smrj 1923446Smrj if (value & AGP_APER_128M_MASK) { 1933446Smrj switch (value & AGP_APER_128M_MASK) { 1943446Smrj case AGP_APER_4M: 1953446Smrj size = 4; /* 4M */ 1963446Smrj break; 1973446Smrj case AGP_APER_8M: 1983446Smrj size = 8; /* 8M */ 1993446Smrj break; 2003446Smrj case AGP_APER_16M: 2013446Smrj size = 16; /* 16M */ 2023446Smrj break; 2033446Smrj case AGP_APER_32M: 2043446Smrj size = 32; /* 32M */ 2053446Smrj break; 2063446Smrj case AGP_APER_64M: 2073446Smrj size = 64; /* 64M */ 2083446Smrj break; 2093446Smrj case AGP_APER_128M: 2103446Smrj size = 128; /* 128M */ 2113446Smrj break; 2123446Smrj default: 2133446Smrj size = 0; /* not true */ 2143446Smrj } 2153446Smrj } else { 2163446Smrj switch (value & AGP_APER_4G_MASK) { 2173446Smrj case AGP_APER_256M: 2183446Smrj size = 256; /* 256 M */ 2193446Smrj break; 2203446Smrj case AGP_APER_512M: 2213446Smrj size = 512; /* 512 M */ 2223446Smrj break; 2233446Smrj case AGP_APER_1024M: 2243446Smrj size = 1024; /* 1024 M */ 2253446Smrj break; 2263446Smrj case AGP_APER_2048M: 2273446Smrj size = 2048; /* 2048 M */ 2283446Smrj break; 2293446Smrj case AGP_APER_4G: 2303446Smrj size = 4096; /* 4096 M */ 2313446Smrj break; 2323446Smrj default: 2333446Smrj size = 0; /* not true */ 2343446Smrj } 2353446Smrj } 2363446Smrj /* 2373446Smrj * In some cases, there is no APSIZE register, so the size value 2383446Smrj * of 256M could be wrong. Check the value by reading the size of 2393446Smrj * the first register which was set in the PCI configuration space. 2403446Smrj */ 2413446Smrj if (size == 256) { 2423446Smrj if (ddi_dev_regsize(softstate->tsoft_dip, 2433446Smrj AGP_TARGET_BAR1, (off_t *)®size) == DDI_FAILURE) 2443446Smrj return (0); 2453446Smrj 2463446Smrj if (MB2BYTES(size) != regsize) { 2473446Smrj TARGETDB_PRINT2((CE_WARN, 2483446Smrj "APSIZE 256M doesn't match regsize %lx", 2493446Smrj regsize)); 2503446Smrj TARGETDB_PRINT2((CE_WARN, "Use regsize instead")); 2513446Smrj size = BYTES2MB(regsize); 2523446Smrj } 2533446Smrj } 2543446Smrj 2553446Smrj return (size); 2563446Smrj } 2573446Smrj 2583446Smrj static void 2593446Smrj agp_target_set_gartaddr(agp_target_softstate_t *softstate, uint32_t gartaddr) 2603446Smrj { 2613446Smrj ASSERT(softstate->tsoft_acaptr); 2623446Smrj 2633446Smrj /* Disable the GTLB for Intel chipsets */ 2643446Smrj pci_config_put16(softstate->tsoft_pcihdl, 2653446Smrj softstate->tsoft_acaptr + AGP_CONF_CONTROL, 0x0000); 2663446Smrj 2673446Smrj pci_config_put32(softstate->tsoft_pcihdl, 2683446Smrj softstate->tsoft_acaptr + AGP_CONF_ATTBASE, 2693446Smrj gartaddr & AGP_ATTBASE_MASK); 2703446Smrj } 2713446Smrj 2723446Smrj static size_t 2733446Smrj i8xx_biosmem_detect(agp_target_softstate_t *softstate) 2743446Smrj { 2753446Smrj uint8_t memval; 2763446Smrj size_t kbytes; 2773446Smrj 2783446Smrj switch (softstate->tsoft_devid) { 2793446Smrj case INTEL_BR_810: 2803446Smrj case INTEL_BR_810DC: 2813446Smrj case INTEL_BR_810E: 2823446Smrj memval = pci_config_get8(softstate->tsoft_pcihdl, 2833446Smrj I810_CONF_SMRAM); 2843446Smrj switch (memval & I810_GMS_MASK) { 2853446Smrj case 0x80: 2863446Smrj kbytes = 512; /* 512K preallocated memory */ 2873446Smrj break; 2883446Smrj case 0xc0: 2893446Smrj kbytes = 1024; /* 1024K preallocated memory */ 2903446Smrj break; 2913446Smrj default: 2923446Smrj kbytes = 0; /* an unexpected case */ 2933446Smrj } 2943446Smrj break; 2953446Smrj case INTEL_BR_830M: 2963446Smrj case INTEL_BR_845: 2973446Smrj memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC); 2983446Smrj switch (memval & I8XX_GC_MODE_MASK) { 2993446Smrj case I8XX_GC_MODE2: 3003446Smrj kbytes = 512; /* 512K preallocated memory */ 3013446Smrj break; 3023446Smrj case I8XX_GC_MODE3: 3033446Smrj kbytes = 1024; /* 1M preallocated memory */ 3043446Smrj break; 3053446Smrj case I8XX_GC_MODE4: 3063446Smrj kbytes = 8 * 1024; /* 8M preallocated memory */ 3073446Smrj break; 3083446Smrj default: 3093446Smrj kbytes = 0; /* an unexpected case */ 3103446Smrj } 3113446Smrj break; 3123446Smrj case INTEL_BR_855GM: 3133446Smrj memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC); 3143446Smrj switch (memval & I8XX_GC_MODE_MASK) { 3153446Smrj case I8XX_GC_MODE1: 3163446Smrj kbytes = 1024; /* 1M preallocated memory */ 3173446Smrj break; 3183446Smrj case I8XX_GC_MODE2: 3193446Smrj kbytes = 4 * 1024; /* 4M preallocated memory */ 3203446Smrj break; 3213446Smrj case I8XX_GC_MODE3: 3223446Smrj kbytes = 8 * 1024; /* 8M preallocated memory */ 3233446Smrj break; 3243446Smrj case I8XX_GC_MODE4: 3253446Smrj kbytes = 16 * 1024; /* 16M preallocated memory */ 3263446Smrj break; 3273446Smrj case I8XX_GC_MODE5: 3283446Smrj kbytes = 32 * 1024; /* 32M preallocated memory */ 3293446Smrj break; 3303446Smrj default: 3313446Smrj kbytes = 0; /* an unexpected case */ 3323446Smrj } 3333446Smrj break; 3343446Smrj case INTEL_BR_865: 335*4478Skz151634 case INTEL_BR_915GM: 3363446Smrj memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC); 3373446Smrj switch (memval & I8XX_GC_MODE_MASK) { 3383446Smrj case I8XX_GC_MODE1: 3393446Smrj kbytes = 1024; /* 1M preallocated memory */ 3403446Smrj break; 3413446Smrj case I8XX_GC_MODE3: 3423446Smrj kbytes = 8 * 1024; /* 8M preallocated memory */ 3433446Smrj break; 3443527Sms148562 /* 345*4478Skz151634 * There is no option for 16M in 915GM datasheet, 3463527Sms148562 * but some BIOS add this option for 16M support. 3473527Sms148562 */ 3483446Smrj case I8XX_GC_MODE4: 3493446Smrj kbytes = 16 * 1024; /* 16M preallocated memory */ 3503446Smrj break; 3513446Smrj default: 3523446Smrj kbytes = 0; /* an unexpected case */ 3533446Smrj } 3543446Smrj break; 355*4478Skz151634 case INTEL_BR_915: 3563446Smrj case INTEL_BR_945: 3574303Skz151634 case INTEL_BR_945GM: 358*4478Skz151634 case INTEL_BR_946GZ: 359*4478Skz151634 case INTEL_BR_965G1: 360*4478Skz151634 case INTEL_BR_965G2: 361*4478Skz151634 case INTEL_BR_965Q: 362*4478Skz151634 case INTEL_BR_965GM: 3633446Smrj memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC); 3643446Smrj switch (memval & I8XX_GC_MODE_MASK) { 3653446Smrj case I8XX_GC_MODE1: 3663446Smrj kbytes = 1024; /* 1M preallocated memory */ 3673446Smrj break; 3683446Smrj case I8XX_GC_MODE3: 3693446Smrj kbytes = 8 * 1024; /* 8M preallocated memory */ 3703446Smrj break; 3713446Smrj default: 3723446Smrj kbytes = 0; /* an unexpected case */ 3733446Smrj } 3743446Smrj break; 3753446Smrj default: 3763446Smrj kbytes = 0; 3773446Smrj } 3783446Smrj 379*4478Skz151634 TARGETDB_PRINT2((CE_NOTE, 380*4478Skz151634 "i8xx_biosmem_detect: %ldKB BIOS pre-allocated memory detected", 381*4478Skz151634 kbytes)); 3823446Smrj return (kbytes); 3833446Smrj } 3843446Smrj 3853446Smrj /*ARGSUSED*/ 3863446Smrj static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 3873446Smrj void *arg, void **resultp) 3883446Smrj { 3893446Smrj agp_target_softstate_t *st; 3903446Smrj int instance, rval = DDI_FAILURE; 3913446Smrj dev_t dev; 3923446Smrj 3933446Smrj switch (cmd) { 3943446Smrj case DDI_INFO_DEVT2DEVINFO: 3953446Smrj dev = (dev_t)arg; 3963446Smrj instance = DEV2INST(dev); 3973446Smrj st = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 3983446Smrj if (st != NULL) { 3993446Smrj mutex_enter(&st->tsoft_lock); 4003446Smrj *resultp = st->tsoft_dip; 4013446Smrj mutex_exit(&st->tsoft_lock); 4023446Smrj rval = DDI_SUCCESS; 4033446Smrj } else 4043446Smrj *resultp = NULL; 4053446Smrj 4063446Smrj break; 4073446Smrj case DDI_INFO_DEVT2INSTANCE: 4083446Smrj dev = (dev_t)arg; 4093446Smrj instance = DEV2INST(dev); 4103446Smrj *resultp = (void *)(uintptr_t)instance; 4113446Smrj rval = DDI_SUCCESS; 4123446Smrj default: 4133446Smrj break; 4143446Smrj } 4153446Smrj 4163446Smrj return (rval); 4173446Smrj } 4183446Smrj 4193446Smrj static int 4203446Smrj agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 4213446Smrj { 4223446Smrj agp_target_softstate_t *softstate; 4233446Smrj int instance; 4243446Smrj int status; 4253446Smrj 4263446Smrj if (cmd != DDI_ATTACH) 4273446Smrj return (DDI_FAILURE); 4283446Smrj 4293446Smrj instance = ddi_get_instance(dip); 4303446Smrj 4313446Smrj if (ddi_soft_state_zalloc(agptarget_glob_soft_handle, instance) != 4323446Smrj DDI_SUCCESS) 4333446Smrj return (DDI_FAILURE); 4343446Smrj 4353446Smrj softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 4363446Smrj mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL); 4373446Smrj softstate->tsoft_dip = dip; 4383446Smrj status = pci_config_setup(dip, &softstate->tsoft_pcihdl); 4393446Smrj if (status != DDI_SUCCESS) { 4403446Smrj ddi_soft_state_free(agptarget_glob_soft_handle, instance); 4413446Smrj return (DDI_FAILURE); 4423446Smrj } 4433446Smrj 4443446Smrj softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl, 4453446Smrj PCI_CONF_VENID); 4463446Smrj softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl); 4473446Smrj if (softstate->tsoft_acaptr == 0) { 4483446Smrj /* Make a correction for some Intel chipsets */ 4493446Smrj if ((softstate->tsoft_devid & VENDOR_ID_MASK) == 4503446Smrj INTEL_VENDOR_ID) 4513446Smrj softstate->tsoft_acaptr = AGP_CAP_OFF_DEF; 4523446Smrj else 4533446Smrj return (DDI_FAILURE); 4543446Smrj } 4553446Smrj 4563446Smrj status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR, 4573446Smrj INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0); 4583446Smrj 4593446Smrj if (status != DDI_SUCCESS) { 4603446Smrj pci_config_teardown(&softstate->tsoft_pcihdl); 4613446Smrj ddi_soft_state_free(agptarget_glob_soft_handle, instance); 4623446Smrj return (DDI_FAILURE); 4633446Smrj } 4643446Smrj 4653446Smrj return (DDI_SUCCESS); 4663446Smrj } 4673446Smrj 4683446Smrj /*ARGSUSED*/ 4693446Smrj static int 4703446Smrj agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 4713446Smrj { 4723446Smrj int instance; 4733446Smrj agp_target_softstate_t *softstate; 4743446Smrj 4753446Smrj if (cmd != DDI_DETACH) 4763446Smrj return (DDI_FAILURE); 4773446Smrj 4783446Smrj instance = ddi_get_instance(dip); 4793446Smrj 4803446Smrj softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 4813446Smrj 4823446Smrj ddi_remove_minor_node(dip, AGPTARGET_NAME); 4833446Smrj pci_config_teardown(&softstate->tsoft_pcihdl); 4843446Smrj mutex_destroy(&softstate->tsoft_lock); 4853446Smrj ddi_soft_state_free(agptarget_glob_soft_handle, instance); 4863446Smrj return (DDI_SUCCESS); 4873446Smrj } 4883446Smrj 4893446Smrj /*ARGSUSED*/ 4903446Smrj static int 4913446Smrj agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 4923446Smrj cred_t *cred, int *rval) 4933446Smrj { 4943446Smrj int instance = DEV2INST(dev); 4953446Smrj agp_target_softstate_t *st; 4963446Smrj static char kernel_only[] = 4973446Smrj "amd64_gart_ioctl: is a kernel only ioctl"; 4983446Smrj 4993446Smrj if (!(mode & FKIOCTL)) { 5003446Smrj TARGETDB_PRINT2((CE_CONT, kernel_only)); 5013446Smrj return (ENXIO); 5023446Smrj } 5033446Smrj st = GETSOFTC(instance); 5043446Smrj 5053446Smrj if (st == NULL) 5063446Smrj return (ENXIO); 5073446Smrj 5083446Smrj mutex_enter(&st->tsoft_lock); 5093446Smrj 5103446Smrj switch (cmd) { 5113446Smrj case CHIP_DETECT: 5123446Smrj { 5133446Smrj int type; 5143446Smrj switch (st->tsoft_devid & VENDOR_ID_MASK) { 5153446Smrj case INTEL_VENDOR_ID: 5163446Smrj type = CHIP_IS_INTEL; 5173446Smrj break; 5183446Smrj case AMD_VENDOR_ID: 5193446Smrj type = CHIP_IS_AMD; 5203446Smrj break; 5213446Smrj default: 5223446Smrj type = 0; 5233446Smrj } 5243446Smrj if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) { 5253446Smrj mutex_exit(&st->tsoft_lock); 5263446Smrj return (EFAULT); 5273446Smrj } 5283446Smrj 5293446Smrj break; 5303446Smrj } 5313446Smrj case I8XX_GET_PREALLOC_SIZE: 5323446Smrj { 5333446Smrj size_t prealloc_size; 5343446Smrj 5353446Smrj if ((st->tsoft_devid & VENDOR_ID_MASK) != 5363446Smrj INTEL_VENDOR_ID) { 5373446Smrj mutex_exit(&st->tsoft_lock); 5383446Smrj return (EINVAL); 5393446Smrj } 5403446Smrj 5413446Smrj prealloc_size = i8xx_biosmem_detect(st); 5423446Smrj if (ddi_copyout(&prealloc_size, (void *)data, 5433446Smrj sizeof (size_t), mode)) { 5443446Smrj mutex_exit(&st->tsoft_lock); 5453446Smrj return (EFAULT); 5463446Smrj } 5473446Smrj 5483446Smrj break; 5493446Smrj } 5503446Smrj case AGP_TARGET_GETINFO: 5513446Smrj { 5523446Smrj i_agp_info_t info; 5533446Smrj uint32_t value; 5543446Smrj off_t cap; 5553446Smrj 5563446Smrj ASSERT(st->tsoft_acaptr); 5573446Smrj 5583446Smrj cap = st->tsoft_acaptr; 5593446Smrj value = pci_config_get32(st->tsoft_pcihdl, cap); 5603446Smrj info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf); 5613446Smrj info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf); 5623446Smrj info.iagp_devid = st->tsoft_devid; 5633446Smrj info.iagp_mode = pci_config_get32(st->tsoft_pcihdl, 5644303Skz151634 cap + AGP_CONF_STATUS); 5653446Smrj info.iagp_aperbase = agp_target_get_apbase(st); 5663446Smrj info.iagp_apersize = agp_target_get_apsize(st); 5673446Smrj 5683446Smrj if (ddi_copyout(&info, (void *)data, 5693446Smrj sizeof (i_agp_info_t), mode)) { 5703446Smrj mutex_exit(&st->tsoft_lock); 5713446Smrj return (EFAULT); 5723446Smrj } 5733446Smrj break; 5743446Smrj 5753446Smrj } 5763446Smrj /* 5773446Smrj * This ioctl is only for Intel AGP chipsets. 5783446Smrj * It is not necessary for the AMD8151 AGP bridge, because 5793446Smrj * this register in the AMD8151 does not control any hardware. 5803446Smrj * It is only provided for compatibility with an Intel AGP bridge. 5813446Smrj * Please refer to the <<AMD8151 data sheet>> page 24, 5823446Smrj * AGP device GART pointer. 5833446Smrj */ 5843446Smrj case AGP_TARGET_SET_GATTADDR: 5853446Smrj { 5863446Smrj uint32_t gartaddr; 5873446Smrj 5883446Smrj if (ddi_copyin((void *)data, &gartaddr, 5893446Smrj sizeof (uint32_t), mode)) { 5903446Smrj mutex_exit(&st->tsoft_lock); 5913446Smrj return (EFAULT); 5923446Smrj } 5933446Smrj 5943446Smrj agp_target_set_gartaddr(st, gartaddr); 5953446Smrj break; 5963446Smrj } 5973446Smrj case AGP_TARGET_SETCMD: 5983446Smrj { 5993446Smrj uint32_t command; 6003446Smrj 6013446Smrj if (ddi_copyin((void *)data, &command, 6023446Smrj sizeof (uint32_t), mode)) { 6033446Smrj mutex_exit(&st->tsoft_lock); 6043446Smrj return (EFAULT); 6053446Smrj } 6063446Smrj 6073446Smrj ASSERT(st->tsoft_acaptr); 6083446Smrj 6093446Smrj pci_config_put32(st->tsoft_pcihdl, 6103446Smrj st->tsoft_acaptr + AGP_CONF_COMMAND, 6113446Smrj command); 6123446Smrj break; 6133446Smrj 6143446Smrj } 6153446Smrj case AGP_TARGET_FLUSH_GTLB: 6163446Smrj { 6173446Smrj uint16_t value; 6183446Smrj 6193446Smrj ASSERT(st->tsoft_acaptr); 6203446Smrj 6213446Smrj value = pci_config_get16(st->tsoft_pcihdl, 6223446Smrj st->tsoft_acaptr + AGP_CONF_CONTROL); 6233446Smrj value &= ~AGPCTRL_GTLBEN; 6243446Smrj pci_config_put16(st->tsoft_pcihdl, 6253446Smrj st->tsoft_acaptr + AGP_CONF_CONTROL, value); 6263446Smrj value |= AGPCTRL_GTLBEN; 6273446Smrj pci_config_put16(st->tsoft_pcihdl, 6283446Smrj st->tsoft_acaptr + AGP_CONF_CONTROL, value); 6293446Smrj 6303446Smrj break; 6313446Smrj } 6323446Smrj case AGP_TARGET_CONFIGURE: 6333446Smrj { 6343446Smrj uint8_t value; 6353446Smrj 6363446Smrj ASSERT(st->tsoft_acaptr); 6373446Smrj 6383446Smrj value = pci_config_get8(st->tsoft_pcihdl, 6393446Smrj st->tsoft_acaptr + AGP_CONF_MISC); 6403446Smrj value |= AGP_MISC_APEN; 6413446Smrj pci_config_put8(st->tsoft_pcihdl, 6423446Smrj st->tsoft_acaptr + AGP_CONF_MISC, value); 6433446Smrj break; 6443446Smrj 6453446Smrj } 6463446Smrj case AGP_TARGET_UNCONFIG: 6473446Smrj { 6483446Smrj uint32_t value1; 6493446Smrj uint8_t value2; 6503446Smrj 6513446Smrj ASSERT(st->tsoft_acaptr); 6523446Smrj 6533446Smrj pci_config_put16(st->tsoft_pcihdl, 6543446Smrj st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0); 6553446Smrj 6563446Smrj value2 = pci_config_get8(st->tsoft_pcihdl, 6573446Smrj st->tsoft_acaptr + AGP_CONF_MISC); 6583446Smrj value2 &= ~AGP_MISC_APEN; 6593446Smrj pci_config_put8(st->tsoft_pcihdl, 6603446Smrj st->tsoft_acaptr + AGP_CONF_MISC, value2); 6613446Smrj 6623446Smrj value1 = pci_config_get32(st->tsoft_pcihdl, 6633446Smrj st->tsoft_acaptr + AGP_CONF_COMMAND); 6643446Smrj value1 &= ~AGPCMD_AGPEN; 6653446Smrj pci_config_put32(st->tsoft_pcihdl, 6663446Smrj st->tsoft_acaptr + AGP_CONF_COMMAND, 6673446Smrj value1); 6683446Smrj 6693446Smrj pci_config_put32(st->tsoft_pcihdl, 6703446Smrj st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0); 6713446Smrj 6723446Smrj break; 6733446Smrj } 6743446Smrj 6753446Smrj default: 6763446Smrj mutex_exit(&st->tsoft_lock); 6773446Smrj return (ENXIO); 6783446Smrj } /* end switch */ 6793446Smrj 6803446Smrj mutex_exit(&st->tsoft_lock); 6813446Smrj 6823446Smrj return (0); 6833446Smrj } 6843446Smrj 6853446Smrj /*ARGSUSED*/ 6863446Smrj static int 6873446Smrj agp_target_open(dev_t *devp, int flag, int otyp, cred_t *cred) 6883446Smrj { 6893446Smrj int instance = DEV2INST(*devp); 6903446Smrj agp_target_softstate_t *st; 6913446Smrj 6923446Smrj if (!(flag & FKLYR)) 6933446Smrj return (ENXIO); 6943446Smrj 6953446Smrj st = GETSOFTC(instance); 6963446Smrj 6973446Smrj if (st == NULL) 6983446Smrj return (ENXIO); 6993446Smrj 7003446Smrj return (0); 7013446Smrj } 7023446Smrj 7033446Smrj /*ARGSUSED*/ 7043446Smrj static int 7053446Smrj agp_target_close(dev_t dev, int flag, int otyp, cred_t *cred) 7063446Smrj { 7073446Smrj int instance = DEV2INST(dev); 7083446Smrj agp_target_softstate_t *st; 7093446Smrj 7103446Smrj st = GETSOFTC(instance); 7113446Smrj 7123446Smrj if (st == NULL) 7133446Smrj return (ENXIO); 7143446Smrj 7153446Smrj return (0); 7163446Smrj } 7173446Smrj 7183446Smrj static struct cb_ops agp_target_cb_ops = { 7193446Smrj agp_target_open, /* cb_open */ 7203446Smrj agp_target_close, /* cb_close */ 7213446Smrj nodev, /* cb_strategy */ 7223446Smrj nodev, /* cb_print */ 7233446Smrj nodev, /* cb_dump */ 7243446Smrj nodev, /* cb_read() */ 7253446Smrj nodev, /* cb_write() */ 7263446Smrj agp_target_ioctl, /* cb_ioctl */ 7273446Smrj nodev, /* cb_devmap */ 7283446Smrj nodev, /* cb_mmap */ 7293446Smrj nodev, /* cb_segmap */ 7303446Smrj nochpoll, /* cb_chpoll */ 7313446Smrj ddi_prop_op, /* cb_prop_op */ 7323446Smrj 0, /* cb_stream */ 7333446Smrj D_NEW | D_MP, /* cb_flag */ 7343446Smrj CB_REV, /* cb_ops version? */ 7353446Smrj nodev, /* cb_aread() */ 7363446Smrj nodev, /* cb_awrite() */ 7373446Smrj }; 7383446Smrj 7393446Smrj /* device operations */ 7403446Smrj static struct dev_ops agp_target_ops = { 7413446Smrj DEVO_REV, /* devo_rev */ 7423446Smrj 0, /* devo_refcnt */ 7433446Smrj agptarget_getinfo, /* devo_getinfo */ 7443446Smrj nulldev, /* devo_identify */ 7453446Smrj nulldev, /* devo_probe */ 7463446Smrj agp_target_attach, /* devo_attach */ 7473446Smrj agp_target_detach, /* devo_detach */ 7483446Smrj nodev, /* devo_reset */ 7493446Smrj &agp_target_cb_ops, /* devo_cb_ops */ 7503446Smrj 0, /* devo_bus_ops */ 7513446Smrj 0, /* devo_power */ 7523446Smrj }; 7533446Smrj 7543446Smrj static struct modldrv modldrv = { 7553446Smrj &mod_driverops, 7563446Smrj "AGP target driver v%I%", 7573446Smrj &agp_target_ops, 7583446Smrj }; 7593446Smrj 7603446Smrj static struct modlinkage modlinkage = { 7613446Smrj MODREV_1, /* MODREV_1 is indicated by manual */ 7623446Smrj {&modldrv, NULL, NULL, NULL} 7633446Smrj }; 7643446Smrj 7653446Smrj int 7663446Smrj _init(void) 7673446Smrj { 7683446Smrj int ret; 7693446Smrj 7703446Smrj ret = ddi_soft_state_init(&agptarget_glob_soft_handle, 7713446Smrj sizeof (agp_target_softstate_t), 1); 7723446Smrj 7733446Smrj if (ret) 7743446Smrj goto err1; 7753446Smrj 7763446Smrj if ((ret = mod_install(&modlinkage)) != 0) { 7773446Smrj goto err2; 7783446Smrj } 7793446Smrj 7803446Smrj return (DDI_SUCCESS); 7813446Smrj err2: 7823446Smrj ddi_soft_state_fini(&agptarget_glob_soft_handle); 7833446Smrj err1: 7843446Smrj return (ret); 7853446Smrj } 7863446Smrj 7873446Smrj int 7883446Smrj _info(struct modinfo *modinfop) 7893446Smrj { 7903446Smrj return (mod_info(&modlinkage, modinfop)); 7913446Smrj } 7923446Smrj 7933446Smrj int 7943446Smrj _fini(void) 7953446Smrj { 7963446Smrj int ret; 7973446Smrj 7983446Smrj if ((ret = mod_remove(&modlinkage)) == 0) { 7993446Smrj ddi_soft_state_fini(&agptarget_glob_soft_handle); 8003446Smrj } 8013446Smrj return (ret); 8023446Smrj } 803