Home | History | Annotate | Download | only in agpgart
      1 /*
      2  * Copyright (c) 2009, Intel Corporation.
      3  * All Rights Reserved.
      4  */
      5 
      6 /*
      7  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
      8  * Use is subject to license terms.
      9  */
     10 /*
     11  * Portions Philip Brown phil (at) bolthole.com Dec 2001
     12  */
     13 
     14 
     15 /*
     16  * agpgart driver
     17  *
     18  * This driver is primary targeted at providing memory support for INTEL
     19  * AGP device, INTEL memory less video card, and AMD64 cpu GART devices.
     20  * So there are four main architectures, ARC_IGD810, ARC_IGD830, ARC_INTELAGP,
     21  * ARC_AMD64AGP to agpgart driver. However, the memory
     22  * interfaces are the same for these architectures. The difference is how to
     23  * manage the hardware GART table for them.
     24  *
     25  * For large memory allocation, this driver use direct mapping to userland
     26  * application interface to save kernel virtual memory .
     27  */
     28 
     29 #include <sys/types.h>
     30 #include <sys/pci.h>
     31 #include <sys/systm.h>
     32 #include <sys/conf.h>
     33 #include <sys/file.h>
     34 #include <sys/kstat.h>
     35 #include <sys/stat.h>
     36 #include <sys/modctl.h>
     37 #include <sys/ddi.h>
     38 #include <sys/sunddi.h>
     39 #include <sys/sunldi.h>
     40 #include <sys/policy.h>
     41 #include <sys/ddidevmap.h>
     42 #include <vm/seg_dev.h>
     43 #include <sys/pmem.h>
     44 #include <sys/agpgart.h>
     45 #include <sys/agp/agpdefs.h>
     46 #include <sys/agp/agpgart_impl.h>
     47 #include <sys/agp/agpamd64gart_io.h>
     48 #include <sys/agp/agpmaster_io.h>
     49 #include <sys/agp/agptarget_io.h>
     50 
     51 /* Dynamic debug support */
     52 int agp_debug_var = 0;
     53 #define	AGPDB_PRINT1(fmt)	if (agp_debug_var == 1) cmn_err fmt
     54 #define	AGPDB_PRINT2(fmt)	if (agp_debug_var >= 1) cmn_err fmt
     55 
     56 /* Driver global softstate handle */
     57 static void *agpgart_glob_soft_handle;
     58 
     59 #define	MAX_INSTNUM			16
     60 
     61 #define	AGP_DEV2INST(devt)	(getminor((devt)) >> 4)
     62 #define	AGP_INST2MINOR(instance)	((instance) << 4)
     63 #define	IS_INTEL_830(type)	((type) == ARC_IGD830)
     64 #define	IS_TRUE_AGP(type)	(((type) == ARC_INTELAGP) || \
     65 	((type) == ARC_AMD64AGP))
     66 
     67 #define	AGP_HASH_NODE	1024
     68 
     69 static void
     70 list_head_init(struct list_head  *head) {
     71 	struct	list_head	*entry,	*tmp;
     72 	/* HASH for accelerate */
     73 	entry = kmem_zalloc(AGP_HASH_NODE *
     74 		sizeof (struct list_head), KM_SLEEP);
     75 	head->next = entry;
     76 	for (int i = 0; i < AGP_HASH_NODE; i++) {
     77 	tmp = &entry[i];
     78 	tmp->next = tmp;
     79 	tmp->prev = tmp;
     80 	tmp->gttseg = NULL;
     81 	}
     82 }
     83 
     84 static void
     85 list_head_add_new(struct list_head	*head,
     86 		igd_gtt_seg_t	*gttseg)
     87 {
     88 	struct list_head  *entry, *tmp;
     89 	int key;
     90 	entry = kmem_zalloc(sizeof (*entry), KM_SLEEP);
     91 	key = gttseg->igs_pgstart % AGP_HASH_NODE;
     92 	tmp = &head->next[key];
     93 	tmp->next->prev = entry;
     94 	entry->next = tmp->next;
     95 	entry->prev = tmp;
     96 	tmp->next = entry;
     97 	entry->gttseg = gttseg;
     98 }
     99 
    100 static void
    101 list_head_del(struct list_head	*entry) {
    102 	(entry)->next->prev = (entry)->prev;      \
    103 	(entry)->prev->next = (entry)->next;      \
    104 	(entry)->gttseg = NULL; \
    105 }
    106 
    107 #define	list_head_for_each_safe(entry,	temp,	head)	\
    108 	for (int key = 0; key < AGP_HASH_NODE; key++)	\
    109 	for (entry = (&(head)->next[key])->next, temp = (entry)->next;	\
    110 		entry != &(head)->next[key];	\
    111 		entry = temp, temp = temp->next)
    112 
    113 
    114 #define	agpinfo_default_to_32(v, v32)	\
    115 	{	\
    116 		(v32).agpi32_version = (v).agpi_version;	\
    117 		(v32).agpi32_devid = (v).agpi_devid;	\
    118 		(v32).agpi32_mode = (v).agpi_mode;	\
    119 		(v32).agpi32_aperbase = (uint32_t)(v).agpi_aperbase;	\
    120 		(v32).agpi32_apersize = (uint32_t)(v).agpi_apersize;	\
    121 		(v32).agpi32_pgtotal = (v).agpi_pgtotal;	\
    122 		(v32).agpi32_pgsystem = (v).agpi_pgsystem;	\
    123 		(v32).agpi32_pgused = (v).agpi_pgused;	\
    124 	}
    125 
    126 static ddi_dma_attr_t agpgart_dma_attr = {
    127 	DMA_ATTR_V0,
    128 	0U,				/* dma_attr_addr_lo */
    129 	0xffffffffU,			/* dma_attr_addr_hi */
    130 	0xffffffffU,			/* dma_attr_count_max */
    131 	(uint64_t)AGP_PAGE_SIZE,	/* dma_attr_align */
    132 	1,				/* dma_attr_burstsizes */
    133 	1,				/* dma_attr_minxfer */
    134 	0xffffffffU,			/* dma_attr_maxxfer */
    135 	0xffffffffU,			/* dma_attr_seg */
    136 	1,				/* dma_attr_sgllen, variable */
    137 	4,				/* dma_attr_granular */
    138 	0				/* dma_attr_flags */
    139 };
    140 
    141 /*
    142  * AMD64 supports gart table above 4G. See alloc_gart_table.
    143  */
    144 static ddi_dma_attr_t garttable_dma_attr = {
    145 	DMA_ATTR_V0,
    146 	0U,				/* dma_attr_addr_lo */
    147 	0xffffffffU,			/* dma_attr_addr_hi */
    148 	0xffffffffU,			/* dma_attr_count_max */
    149 	(uint64_t)AGP_PAGE_SIZE,	/* dma_attr_align */
    150 	1,				/* dma_attr_burstsizes */
    151 	1,				/* dma_attr_minxfer */
    152 	0xffffffffU,			/* dma_attr_maxxfer */
    153 	0xffffffffU,			/* dma_attr_seg */
    154 	1,				/* dma_attr_sgllen, variable */
    155 	4,				/* dma_attr_granular */
    156 	0				/* dma_attr_flags */
    157 };
    158 
    159 /*
    160  * AGPGART table need a physical contiguous memory. To assure that
    161  * each access to gart table is strongly ordered and uncachable,
    162  * we use DDI_STRICTORDER_ACC.
    163  */
    164 static ddi_device_acc_attr_t gart_dev_acc_attr = {
    165 	DDI_DEVICE_ATTR_V0,
    166 	DDI_NEVERSWAP_ACC,
    167 	DDI_STRICTORDER_ACC	/* must be DDI_STRICTORDER_ACC */
    168 };
    169 
    170 /*
    171  * AGP memory is usually used as texture memory or for a framebuffer, so we
    172  * can set the memory attribute to write combining. Video drivers will
    173  * determine the frame buffer attributes, for example the memory is write
    174  * combinging or non-cachable. However, the interface between Xorg and agpgart
    175  * driver to support attribute selcetion doesn't exist yet. So we set agp memory
    176  * to non-cachable by default now. This attribute might be overridden
    177  * by MTTR in X86.
    178  */
    179 static ddi_device_acc_attr_t mem_dev_acc_attr = {
    180 	DDI_DEVICE_ATTR_V0,
    181 	DDI_NEVERSWAP_ACC,
    182 	DDI_STRICTORDER_ACC	/* Can be DDI_MERGING_OK_ACC */
    183 };
    184 
    185 static keytable_ent_t *
    186 agp_find_bound_keyent(agpgart_softstate_t *softstate, uint32_t pg_offset);
    187 static void
    188 amd64_gart_unregister(amd64_garts_dev_t *cpu_garts);
    189 
    190 
    191 static void
    192 agp_devmap_unmap(devmap_cookie_t handle, void *devprivate,
    193     offset_t off, size_t len, devmap_cookie_t new_handle1,
    194     void **new_devprivate1, devmap_cookie_t new_handle2,
    195     void **new_devprivate2)
    196 {
    197 
    198 	struct keytable_ent *mementry;
    199 	agpgart_softstate_t *softstate;
    200 	agpgart_ctx_t *ctxp, *newctxp1, *newctxp2;
    201 
    202 	ASSERT(AGP_ALIGNED(len) && AGP_ALIGNED(off));
    203 	ASSERT(devprivate);
    204 	ASSERT(handle);
    205 
    206 	ctxp = (agpgart_ctx_t *)devprivate;
    207 	softstate = ctxp->actx_sc;
    208 	ASSERT(softstate);
    209 
    210 	if (new_handle1 != NULL) {
    211 		newctxp1 = kmem_zalloc(sizeof (agpgart_ctx_t), KM_SLEEP);
    212 		newctxp1->actx_sc = softstate;
    213 		newctxp1->actx_off = ctxp->actx_off;
    214 		*new_devprivate1 = newctxp1;
    215 	}
    216 
    217 	if (new_handle2 != NULL) {
    218 		newctxp2 = kmem_zalloc(sizeof (agpgart_ctx_t), KM_SLEEP);
    219 		newctxp2->actx_sc = softstate;
    220 		newctxp2->actx_off = off + len;
    221 		*new_devprivate2 = newctxp2;
    222 	}
    223 
    224 	mutex_enter(&softstate->asoft_instmutex);
    225 	if ((new_handle1 == NULL) && (new_handle2 == NULL)) {
    226 		mementry =
    227 		    agp_find_bound_keyent(softstate, AGP_BYTES2PAGES(off));
    228 		ASSERT(mementry);
    229 		mementry->kte_refcnt--;
    230 	} else if ((new_handle1 != NULL) && (new_handle2 != NULL)) {
    231 		mementry =
    232 		    agp_find_bound_keyent(softstate, AGP_BYTES2PAGES(off));
    233 		ASSERT(mementry);
    234 		mementry->kte_refcnt++;
    235 	}
    236 	ASSERT(mementry->kte_refcnt >= 0);
    237 	mutex_exit(&softstate->asoft_instmutex);
    238 	kmem_free(ctxp, sizeof (struct agpgart_ctx));
    239 }
    240 
    241 /*ARGSUSED*/
    242 static int
    243 agp_devmap_map(devmap_cookie_t handle, dev_t dev,
    244     uint_t flags, offset_t offset, size_t len, void **new_devprivate)
    245 {
    246 	agpgart_softstate_t *softstate;
    247 	int instance;
    248 	struct keytable_ent *mementry;
    249 	agpgart_ctx_t *newctxp;
    250 
    251 	ASSERT(handle);
    252 	instance = AGP_DEV2INST(dev);
    253 	softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
    254 	if (softstate == NULL) {
    255 		AGPDB_PRINT2((CE_WARN, "agp_devmap_map: get soft state err"));
    256 		return (ENXIO);
    257 	}
    258 
    259 	ASSERT(softstate);
    260 	ASSERT(mutex_owned(&softstate->asoft_instmutex));
    261 	ASSERT(len);
    262 	ASSERT(AGP_ALIGNED(offset) && AGP_ALIGNED(len));
    263 
    264 	mementry =
    265 	    agp_find_bound_keyent(softstate, AGP_BYTES2PAGES(offset));
    266 	ASSERT(mementry);
    267 	mementry->kte_refcnt++;
    268 	ASSERT(mementry->kte_refcnt >= 0);
    269 	newctxp = kmem_zalloc(sizeof (agpgart_ctx_t), KM_SLEEP);
    270 	newctxp->actx_off = offset;
    271 	newctxp->actx_sc = softstate;
    272 	*new_devprivate = newctxp;
    273 
    274 	return (0);
    275 }
    276 
    277 /*ARGSUSED*/
    278 static int agp_devmap_dup(devmap_cookie_t handle, void *devprivate,
    279     devmap_cookie_t new_handle, void **new_devprivate)
    280 {
    281 	struct keytable_ent *mementry;
    282 	agpgart_ctx_t *newctxp, *ctxp;
    283 	agpgart_softstate_t *softstate;
    284 
    285 	ASSERT(devprivate);
    286 	ASSERT(handle && new_handle);
    287 
    288 	ctxp = (agpgart_ctx_t *)devprivate;
    289 	ASSERT(AGP_ALIGNED(ctxp->actx_off));
    290 
    291 	newctxp = kmem_zalloc(sizeof (agpgart_ctx_t), KM_SLEEP);
    292 	newctxp->actx_off = ctxp->actx_off;
    293 	newctxp->actx_sc = ctxp->actx_sc;
    294 	softstate = (agpgart_softstate_t *)newctxp->actx_sc;
    295 
    296 	mutex_enter(&softstate->asoft_instmutex);
    297 	mementry = agp_find_bound_keyent(softstate,
    298 	    AGP_BYTES2PAGES(newctxp->actx_off));
    299 	mementry->kte_refcnt++;
    300 	ASSERT(mementry->kte_refcnt >= 0);
    301 	mutex_exit(&softstate->asoft_instmutex);
    302 	*new_devprivate = newctxp;
    303 
    304 	return (0);
    305 }
    306 
    307 struct devmap_callback_ctl agp_devmap_cb = {
    308 	DEVMAP_OPS_REV,		/* rev */
    309 	agp_devmap_map,		/* map */
    310 	NULL,			/* access */
    311 	agp_devmap_dup,		/* dup */
    312 	agp_devmap_unmap,	/* unmap */
    313 };
    314 
    315 /*
    316  * agp_master_regis_byname()
    317  *
    318  * Description:
    319  * 	Open the AGP master device node by device path name and
    320  * 	register the device handle for later operations.
    321  * 	We check all possible driver instance from 0
    322  * 	to MAX_INSTNUM because the master device could be
    323  * 	at any instance number. Only one AGP master is supported.
    324  *
    325  * Arguments:
    326  * 	master_hdlp		AGP master device LDI handle pointer
    327  *	agpgart_l		AGPGART driver LDI identifier
    328  *
    329  * Returns:
    330  * 	-1			failed
    331  * 	0			success
    332  */
    333 static int
    334 agp_master_regis_byname(ldi_handle_t *master_hdlp, ldi_ident_t agpgart_li)
    335 {
    336 	int	i;
    337 	char	buf[MAXPATHLEN];
    338 
    339 	ASSERT(master_hdlp);
    340 	ASSERT(agpgart_li);
    341 
    342 	/*
    343 	 * Search all possible instance numbers for the agp master device.
    344 	 * Only one master device is supported now, so the search ends
    345 	 * when one master device is found.
    346 	 */
    347 	for (i = 0; i < MAX_INSTNUM; i++) {
    348 		(void) snprintf(buf, MAXPATHLEN, "%s%d", AGPMASTER_DEVLINK, i);
    349 		if ((ldi_open_by_name(buf, 0, kcred,
    350 		    master_hdlp, agpgart_li)))
    351 			continue;
    352 		AGPDB_PRINT1((CE_NOTE,
    353 		    "master device found: instance number=%d", i));
    354 		break;
    355 
    356 	}
    357 
    358 	/* AGP master device not found */
    359 	if (i == MAX_INSTNUM)
    360 		return (-1);
    361 
    362 	return (0);
    363 }
    364 
    365 /*
    366  * agp_target_regis_byname()
    367  *
    368  * Description:
    369  * 	This function opens agp bridge device node by
    370  * 	device path name and registers the device handle
    371  * 	for later operations.
    372  * 	We check driver instance from 0 to MAX_INSTNUM
    373  * 	because the master device could be at any instance
    374  * 	number. Only one agp target is supported.
    375  *
    376  *
    377  * Arguments:
    378  *	target_hdlp		AGP target device LDI handle pointer
    379  *	agpgart_l		AGPGART driver LDI identifier
    380  *
    381  * Returns:
    382  * 	-1			failed
    383  * 	0			success
    384  */
    385 static int
    386 agp_target_regis_byname(ldi_handle_t *target_hdlp, ldi_ident_t agpgart_li)
    387 {
    388 	int	i;
    389 	char	buf[MAXPATHLEN];
    390 
    391 	ASSERT(target_hdlp);
    392 	ASSERT(agpgart_li);
    393 
    394 	for (i = 0; i < MAX_INSTNUM; i++) {
    395 		(void) snprintf(buf, MAXPATHLEN, "%s%d", AGPTARGET_DEVLINK, i);
    396 		if ((ldi_open_by_name(buf, 0, kcred,
    397 		    target_hdlp, agpgart_li)))
    398 			continue;
    399 
    400 		AGPDB_PRINT1((CE_NOTE,
    401 		    "bridge device found: instance number=%d", i));
    402 		break;
    403 
    404 	}
    405 
    406 	/* AGP bridge device not found */
    407 	if (i == MAX_INSTNUM) {
    408 		AGPDB_PRINT2((CE_WARN, "bridge device not found"));
    409 		return (-1);
    410 	}
    411 
    412 	return (0);
    413 }
    414 
    415 /*
    416  * amd64_gart_regis_byname()
    417  *
    418  * Description:
    419  * 	Open all amd64 gart device nodes by deice path name and
    420  * 	register the device handles for later operations. Each cpu
    421  * 	has its own amd64 gart device.
    422  *
    423  * Arguments:
    424  * 	cpu_garts		cpu garts device list header
    425  *	agpgart_l		AGPGART driver LDI identifier
    426  *
    427  * Returns:
    428  * 	-1			failed
    429  * 	0			success
    430  */
    431 static int
    432 amd64_gart_regis_byname(amd64_garts_dev_t *cpu_garts, ldi_ident_t agpgart_li)
    433 {
    434 	amd64_gart_dev_list_t	*gart_list;
    435 	int			i;
    436 	char			buf[MAXPATHLEN];
    437 	ldi_handle_t		gart_hdl;
    438 	int			ret;
    439 
    440 	ASSERT(cpu_garts);
    441 	ASSERT(agpgart_li);
    442 
    443 	/*
    444 	 * Search all possible instance numbers for the gart devices.
    445 	 * There can be multiple on-cpu gart devices for Opteron server.
    446 	 */
    447 	for (i = 0; i < MAX_INSTNUM; i++) {
    448 		(void) snprintf(buf, MAXPATHLEN, "%s%d", CPUGART_DEVLINK, i);
    449 		ret = ldi_open_by_name(buf, 0, kcred,
    450 		    &gart_hdl, agpgart_li);
    451 
    452 		if (ret == ENODEV)
    453 			continue;
    454 		else if (ret != 0) { /* There was an error opening the device */
    455 			amd64_gart_unregister(cpu_garts);
    456 			return (ret);
    457 		}
    458 
    459 		AGPDB_PRINT1((CE_NOTE,
    460 		    "amd64 gart device found: instance number=%d", i));
    461 
    462 		gart_list = (amd64_gart_dev_list_t *)
    463 		    kmem_zalloc(sizeof (amd64_gart_dev_list_t), KM_SLEEP);
    464 
    465 		/* Add new item to the head of the gart device list */
    466 		gart_list->gart_devhdl = gart_hdl;
    467 		gart_list->next = cpu_garts->gart_dev_list_head;
    468 		cpu_garts->gart_dev_list_head = gart_list;
    469 		cpu_garts->gart_device_num++;
    470 	}
    471 
    472 	if (cpu_garts->gart_device_num == 0)
    473 		return (ENODEV);
    474 	return (0);
    475 }
    476 
    477 /*
    478  * Unregister agp master device handle
    479  */
    480 static void
    481 agp_master_unregister(ldi_handle_t *master_hdlp)
    482 {
    483 	ASSERT(master_hdlp);
    484 
    485 	if (master_hdlp) {
    486 		(void) ldi_close(*master_hdlp, 0, kcred);
    487 		*master_hdlp = NULL;
    488 	}
    489 }
    490 
    491 /*
    492  * Unregister agp bridge device handle
    493  */
    494 static void
    495 agp_target_unregister(ldi_handle_t *target_hdlp)
    496 {
    497 	if (target_hdlp) {
    498 		(void) ldi_close(*target_hdlp, 0, kcred);
    499 		*target_hdlp = NULL;
    500 	}
    501 }
    502 
    503 /*
    504  * Unregister all amd64 gart device handles
    505  */
    506 static void
    507 amd64_gart_unregister(amd64_garts_dev_t *cpu_garts)
    508 {
    509 	amd64_gart_dev_list_t	*gart_list;
    510 	amd64_gart_dev_list_t	*next;
    511 
    512 	ASSERT(cpu_garts);
    513 
    514 	for (gart_list = cpu_garts->gart_dev_list_head;
    515 	    gart_list; gart_list = next) {
    516 
    517 		ASSERT(gart_list->gart_devhdl);
    518 		(void) ldi_close(gart_list->gart_devhdl, 0, kcred);
    519 		next = gart_list->next;
    520 		/* Free allocated memory */
    521 		kmem_free(gart_list, sizeof (amd64_gart_dev_list_t));
    522 	}
    523 	cpu_garts->gart_dev_list_head = NULL;
    524 	cpu_garts->gart_device_num = 0;
    525 }
    526 
    527 /*
    528  * lyr_detect_master_type()
    529  *
    530  * Description:
    531  * 	This function gets agp master type by querying agp master device.
    532  *
    533  * Arguments:
    534  * 	master_hdlp		agp master device ldi handle pointer
    535  *
    536  * Returns:
    537  * 	-1			unsupported device
    538  * 	DEVICE_IS_I810		i810 series
    539  * 	DEVICE_IS_I810		i830 series
    540  * 	DEVICE_IS_AGP		true agp master
    541  */
    542 static int
    543 lyr_detect_master_type(ldi_handle_t *master_hdlp)
    544 {
    545 	int vtype;
    546 	int err;
    547 
    548 	ASSERT(master_hdlp);
    549 
    550 	/* ldi_ioctl(agpmaster) */
    551 	err = ldi_ioctl(*master_hdlp, DEVICE_DETECT,
    552 	    (intptr_t)&vtype, FKIOCTL, kcred, 0);
    553 	if (err) /* Unsupported graphics device */
    554 		return (-1);
    555 	return (vtype);
    556 }
    557 
    558 /*
    559  * devtect_target_type()
    560  *
    561  * Description:
    562  * 	This function gets the host bridge chipset type by querying the agp
    563  *	target device.
    564  *
    565  * Arguments:
    566  * 	target_hdlp		agp target device LDI handle pointer
    567  *
    568  * Returns:
    569  * 	CHIP_IS_INTEL		Intel agp chipsets
    570  * 	CHIP_IS_AMD		AMD agp chipset
    571  * 	-1			unsupported chipset
    572  */
    573 static int
    574 lyr_detect_target_type(ldi_handle_t *target_hdlp)
    575 {
    576 	int btype;
    577 	int err;
    578 
    579 	ASSERT(target_hdlp);
    580 
    581 	err = ldi_ioctl(*target_hdlp, CHIP_DETECT, (intptr_t)&btype,
    582 	    FKIOCTL, kcred, 0);
    583 	if (err)	/* Unsupported bridge device */
    584 		return (-1);
    585 	return (btype);
    586 }
    587 
    588 /*
    589  * lyr_init()
    590  *
    591  * Description:
    592  * 	This function detects the  graphics system architecture and
    593  * 	registers all relative device handles in a global structure
    594  * 	"agp_regdev". Then it stores the system arc type in driver
    595  * 	soft state.
    596  *
    597  * Arguments:
    598  *	agp_regdev		AGP devices registration struct pointer
    599  *	agpgart_l		AGPGART driver LDI identifier
    600  *
    601  * Returns:
    602  * 	0	System arc supported and agp devices registration successed.
    603  * 	-1	System arc not supported or device registration failed.
    604  */
    605 int
    606 lyr_init(agp_registered_dev_t *agp_regdev, ldi_ident_t agpgart_li)
    607 {
    608 	ldi_handle_t *master_hdlp;
    609 	ldi_handle_t *target_hdlp;
    610 	amd64_garts_dev_t *garts_dev;
    611 	int card_type, chip_type;
    612 	int ret;
    613 
    614 	ASSERT(agp_regdev);
    615 
    616 	bzero(agp_regdev, sizeof (agp_registered_dev_t));
    617 	agp_regdev->agprd_arctype = ARC_UNKNOWN;
    618 	/*
    619 	 * Register agp devices, assuming all instances attached, and
    620 	 * detect which agp architucture this server belongs to. This
    621 	 * must be done before the agpgart driver starts to use layered
    622 	 * driver interfaces.
    623 	 */
    624 	master_hdlp = &agp_regdev->agprd_masterhdl;
    625 	target_hdlp = &agp_regdev->agprd_targethdl;
    626 	garts_dev = &agp_regdev->agprd_cpugarts;
    627 
    628 	/* Check whether the system is amd64 arc */
    629 	if ((ret = amd64_gart_regis_byname(garts_dev, agpgart_li)) == ENODEV) {
    630 		/* No amd64 gart devices */
    631 		AGPDB_PRINT1((CE_NOTE,
    632 		    "lyr_init: this is not an amd64 system"));
    633 		if (agp_master_regis_byname(master_hdlp, agpgart_li)) {
    634 			AGPDB_PRINT2((CE_WARN,
    635 			    "lyr_init: register master device unsuccessful"));
    636 			goto err1;
    637 		}
    638 		if (agp_target_regis_byname(target_hdlp, agpgart_li)) {
    639 			AGPDB_PRINT2((CE_WARN,
    640 			    "lyr_init: register target device unsuccessful"));
    641 			goto err2;
    642 		}
    643 		card_type = lyr_detect_master_type(master_hdlp);
    644 		/*
    645 		 * Detect system arc by master device. If it is a intel
    646 		 * integrated device, finish the detection successfully.
    647 		 */
    648 		switch (card_type) {
    649 		case DEVICE_IS_I810:	/* I810 likewise graphics */
    650 			AGPDB_PRINT1((CE_NOTE,
    651 			    "lyr_init: the system is Intel 810 arch"));
    652 			agp_regdev->agprd_arctype = ARC_IGD810;
    653 			return (0);
    654 		case DEVICE_IS_I830:	/* I830 likewise graphics */
    655 			AGPDB_PRINT1((CE_NOTE,
    656 			    "lyr_init: the system is Intel 830 arch"));
    657 			agp_regdev->agprd_arctype = ARC_IGD830;
    658 			return (0);
    659 		case DEVICE_IS_AGP:	/* AGP graphics */
    660 			break;
    661 		default:		/* Non IGD/AGP graphics */
    662 			AGPDB_PRINT2((CE_WARN,
    663 			    "lyr_init: non-supported master device"));
    664 			goto err3;
    665 		}
    666 
    667 		chip_type = lyr_detect_target_type(target_hdlp);
    668 
    669 		/* Continue to detect AGP arc by target device */
    670 		switch (chip_type) {
    671 		case CHIP_IS_INTEL:	/* Intel chipset */
    672 			AGPDB_PRINT1((CE_NOTE,
    673 			    "lyr_init: Intel AGP arch detected"));
    674 			agp_regdev->agprd_arctype = ARC_INTELAGP;
    675 			return (0);
    676 		case CHIP_IS_AMD:	/* AMD chipset */
    677 			AGPDB_PRINT2((CE_WARN,
    678 			    "lyr_init: no cpu gart, but have AMD64 chipsets"));
    679 			goto err3;
    680 		default:		/* Non supported chipset */
    681 			AGPDB_PRINT2((CE_WARN,
    682 			    "lyr_init: detection can not continue"));
    683 			goto err3;
    684 		}
    685 
    686 	}
    687 
    688 	if (ret)
    689 		return (-1); /* Errors in open amd64 cpu gart devices */
    690 
    691 	/*
    692 	 * AMD64 cpu gart device exsits, continue detection
    693 	 */
    694 	if (agp_master_regis_byname(master_hdlp, agpgart_li)) {
    695 		AGPDB_PRINT1((CE_NOTE, "lyr_init: no AGP master in amd64"));
    696 		goto err1;
    697 	}
    698 
    699 	if (agp_target_regis_byname(target_hdlp, agpgart_li)) {
    700 		AGPDB_PRINT1((CE_NOTE,
    701 		    "lyr_init: no AGP bridge"));
    702 		goto err2;
    703 	}
    704 
    705 	AGPDB_PRINT1((CE_NOTE,
    706 	    "lyr_init: the system is AMD64 AGP architecture"));
    707 
    708 	agp_regdev->agprd_arctype = ARC_AMD64AGP;
    709 
    710 	return (0); /* Finished successfully */
    711 
    712 err3:
    713 	agp_target_unregister(&agp_regdev->agprd_targethdl);
    714 err2:
    715 	agp_master_unregister(&agp_regdev->agprd_masterhdl);
    716 err1:
    717 	/* AMD64 CPU gart registered ? */
    718 	if (ret == 0) {
    719 		amd64_gart_unregister(garts_dev);
    720 	}
    721 	agp_regdev->agprd_arctype = ARC_UNKNOWN;
    722 	return (-1);
    723 }
    724 
    725 void
    726 lyr_end(agp_registered_dev_t *agp_regdev)
    727 {
    728 	ASSERT(agp_regdev);
    729 
    730 	switch (agp_regdev->agprd_arctype) {
    731 	case ARC_IGD810:
    732 	case ARC_IGD830:
    733 	case ARC_INTELAGP:
    734 		agp_master_unregister(&agp_regdev->agprd_masterhdl);
    735 		agp_target_unregister(&agp_regdev->agprd_targethdl);
    736 
    737 		return;
    738 	case ARC_AMD64AGP:
    739 		agp_master_unregister(&agp_regdev->agprd_masterhdl);
    740 		agp_target_unregister(&agp_regdev->agprd_targethdl);
    741 		amd64_gart_unregister(&agp_regdev->agprd_cpugarts);
    742 
    743 		return;
    744 	default:
    745 		ASSERT(0);
    746 		return;
    747 	}
    748 }
    749 
    750 int
    751 lyr_get_info(agp_kern_info_t *info, agp_registered_dev_t *agp_regdev)
    752 {
    753 	ldi_handle_t hdl;
    754 	igd_info_t value1;
    755 	i_agp_info_t value2;
    756 	size_t prealloc_size;
    757 	int err;
    758 
    759 	ASSERT(info);
    760 	ASSERT(agp_regdev);
    761 
    762 	switch (agp_regdev->agprd_arctype) {
    763 	case ARC_IGD810:
    764 		hdl = agp_regdev->agprd_masterhdl;
    765 		err = ldi_ioctl(hdl, I8XX_GET_INFO, (intptr_t)&value1,
    766 		    FKIOCTL, kcred, 0);
    767 		if (err)
    768 			return (-1);
    769 		info->agpki_mdevid = value1.igd_devid;
    770 		info->agpki_aperbase = value1.igd_aperbase;
    771 		info->agpki_apersize = (uint32_t)value1.igd_apersize;
    772 
    773 		hdl = agp_regdev->agprd_targethdl;
    774 		err = ldi_ioctl(hdl, I8XX_GET_PREALLOC_SIZE,
    775 		    (intptr_t)&prealloc_size, FKIOCTL, kcred, 0);
    776 		if (err)
    777 			return (-1);
    778 		info->agpki_presize = prealloc_size;
    779 
    780 		break;
    781 
    782 	case ARC_IGD830:
    783 		hdl = agp_regdev->agprd_masterhdl;
    784 		err = ldi_ioctl(hdl, I8XX_GET_INFO, (intptr_t)&value1,
    785 		    FKIOCTL, kcred, 0);
    786 		if (err)
    787 			return (-1);
    788 		info->agpki_mdevid = value1.igd_devid;
    789 		info->agpki_aperbase = value1.igd_aperbase;
    790 		info->agpki_apersize = (uint32_t)value1.igd_apersize;
    791 
    792 		hdl = agp_regdev->agprd_targethdl;
    793 		err = ldi_ioctl(hdl, I8XX_GET_PREALLOC_SIZE,
    794 		    (intptr_t)&prealloc_size, FKIOCTL, kcred, 0);
    795 		if (err)
    796 			return (-1);
    797 
    798 		/*
    799 		 * Assume all units are kilobytes unless explicitly
    800 		 * stated below:
    801 		 * preallocated GTT memory = preallocated memory - GTT size
    802 		 * 	- scratch page size
    803 		 *
    804 		 * scratch page size = 4
    805 		 * GTT size (KB) = aperture size (MB)
    806 		 * this algorithm came from Xorg source code
    807 		 */
    808 		if (prealloc_size > (info->agpki_apersize + 4))
    809 			prealloc_size =
    810 			    prealloc_size - info->agpki_apersize - 4;
    811 		else {
    812 			AGPDB_PRINT2((CE_WARN, "lyr_get_info: "
    813 			    "pre-allocated memory too small, setting to zero"));
    814 			prealloc_size = 0;
    815 		}
    816 		info->agpki_presize = prealloc_size;
    817 		AGPDB_PRINT2((CE_NOTE,
    818 		    "lyr_get_info: prealloc_size = %ldKB, apersize = %dMB",
    819 		    prealloc_size, info->agpki_apersize));
    820 		break;
    821 	case ARC_INTELAGP:
    822 	case ARC_AMD64AGP:
    823 		/* AGP devices */
    824 		hdl = agp_regdev->agprd_masterhdl;
    825 		err = ldi_ioctl(hdl, AGP_MASTER_GETINFO,
    826 		    (intptr_t)&value2, FKIOCTL, kcred, 0);
    827 		if (err)
    828 			return (-1);
    829 		info->agpki_mdevid = value2.iagp_devid;
    830 		info->agpki_mver = value2.iagp_ver;
    831 		info->agpki_mstatus = value2.iagp_mode;
    832 		hdl = agp_regdev->agprd_targethdl;
    833 		err = ldi_ioctl(hdl, AGP_TARGET_GETINFO,
    834 		    (intptr_t)&value2, FKIOCTL, kcred, 0);
    835 		if (err)
    836 			return (-1);
    837 		info->agpki_tdevid = value2.iagp_devid;
    838 		info->agpki_tver = value2.iagp_ver;
    839 		info->agpki_tstatus = value2.iagp_mode;
    840 		info->agpki_aperbase = value2.iagp_aperbase;
    841 		info->agpki_apersize = (uint32_t)value2.iagp_apersize;
    842 		break;
    843 	default:
    844 		AGPDB_PRINT2((CE_WARN,
    845 		    "lyr_get_info: function doesn't work for unknown arc"));
    846 		return (-1);
    847 	}
    848 	if ((info->agpki_apersize >= MAXAPERMEGAS) ||
    849 	    (info->agpki_apersize == 0) ||
    850 	    (info->agpki_aperbase == 0)) {
    851 		AGPDB_PRINT2((CE_WARN,
    852 		    "lyr_get_info: aperture is not programmed correctly!"));
    853 		return (-1);
    854 	}
    855 
    856 	return (0);
    857 }
    858 
    859 /*
    860  * lyr_i8xx_add_to_gtt()
    861  *
    862  * Description:
    863  * 	This function sets up the integrated video device gtt table
    864  * 	via an ioclt to the AGP master driver.
    865  *
    866  * Arguments:
    867  * 	pg_offset	The start entry to be setup
    868  * 	keyent		Keytable entity pointer
    869  *	agp_regdev	AGP devices registration struct pointer
    870  *
    871  * Returns:
    872  * 	0		success
    873  * 	-1		invalid operations
    874  */
    875 int
    876 lyr_i8xx_add_to_gtt(uint32_t pg_offset, keytable_ent_t *keyent,
    877     agp_registered_dev_t *agp_regdev)
    878 {
    879 	int err = 0;
    880 	int rval;
    881 	ldi_handle_t hdl;
    882 	igd_gtt_seg_t gttseg;
    883 	uint32_t *addrp, i;
    884 	uint32_t npages;
    885 
    886 	ASSERT(keyent);
    887 	ASSERT(agp_regdev);
    888 	gttseg.igs_pgstart =  pg_offset;
    889 	npages = keyent->kte_pages;
    890 	gttseg.igs_npage = npages;
    891 	gttseg.igs_type = keyent->kte_type;
    892 	gttseg.igs_phyaddr = (uint32_t *)kmem_zalloc
    893 	    (sizeof (uint32_t) * gttseg.igs_npage, KM_SLEEP);
    894 
    895 	addrp = gttseg.igs_phyaddr;
    896 	for (i = 0; i < npages; i++, addrp++) {
    897 		*addrp =
    898 		    (uint32_t)((keyent->kte_pfnarray[i]) << GTT_PAGE_SHIFT);
    899 	}
    900 
    901 	hdl = agp_regdev->agprd_masterhdl;
    902 	if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)&gttseg, FKIOCTL,
    903 	    kcred, &rval)) {
    904 		AGPDB_PRINT2((CE_WARN, "lyr_i8xx_add_to_gtt: ldi_ioctl error"));
    905 		AGPDB_PRINT2((CE_WARN, "lyr_i8xx_add_to_gtt: pg_start=0x%x",
    906 		    gttseg.igs_pgstart));
    907 		AGPDB_PRINT2((CE_WARN, "lyr_i8xx_add_to_gtt: pages=0x%x",
    908 		    gttseg.igs_npage));
    909 		AGPDB_PRINT2((CE_WARN, "lyr_i8xx_add_to_gtt: type=0x%x",
    910 		    gttseg.igs_type));
    911 		err = -1;
    912 	}
    913 	kmem_free(gttseg.igs_phyaddr, sizeof (uint32_t) * gttseg.igs_npage);
    914 	return (err);
    915 }
    916 
    917 /*
    918  * lyr_i8xx_remove_from_gtt()
    919  *
    920  * Description:
    921  * 	This function clears the integrated video device gtt table via
    922  * 	an ioctl to the agp master device.
    923  *
    924  * Arguments:
    925  * 	pg_offset	The starting entry to be cleared
    926  * 	npage		The number of entries to be cleared
    927  *	agp_regdev	AGP devices struct pointer
    928  *
    929  * Returns:
    930  * 	0		success
    931  * 	-1		invalid operations
    932  */
    933 int
    934 lyr_i8xx_remove_from_gtt(uint32_t pg_offset, uint32_t npage,
    935     agp_registered_dev_t *agp_regdev)
    936 {
    937 	int			rval;
    938 	ldi_handle_t		hdl;
    939 	igd_gtt_seg_t		gttseg;
    940 
    941 	gttseg.igs_pgstart =  pg_offset;
    942 	gttseg.igs_npage = npage;
    943 
    944 	hdl = agp_regdev->agprd_masterhdl;
    945 	if (ldi_ioctl(hdl, I8XX_REM_GTT, (intptr_t)&gttseg, FKIOCTL,
    946 	    kcred, &rval))
    947 		return (-1);
    948 
    949 	return (0);
    950 }
    951 
    952 /*
    953  * lyr_set_gart_addr()
    954  *
    955  * Description:
    956  *	This function puts the gart table physical address in the
    957  * 	gart base register.
    958  *	Please refer to gart and gtt table base register format for
    959  *	gart base register format in agpdefs.h.
    960  *
    961  * Arguments:
    962  * 	phy_base	The base physical address of gart table
    963  *	agp_regdev	AGP devices registration struct pointer
    964  *
    965  * Returns:
    966  * 	0		success
    967  * 	-1		failed
    968  *
    969  */
    970 
    971 int
    972 lyr_set_gart_addr(uint64_t phy_base, agp_registered_dev_t *agp_regdev)
    973 {
    974 	amd64_gart_dev_list_t	*gart_list;
    975 	ldi_handle_t		hdl;
    976 	int			err = 0;
    977 
    978 	ASSERT(agp_regdev);
    979 	switch (agp_regdev->agprd_arctype) {
    980 	case ARC_IGD810:
    981 	{
    982 		uint32_t base;
    983 
    984 		ASSERT((phy_base & I810_POINTER_MASK) == 0);
    985 		base = (uint32_t)phy_base;
    986 
    987 		hdl = agp_regdev->agprd_masterhdl;
    988 		err = ldi_ioctl(hdl, I810_SET_GTT_BASE,
    989 		    (intptr_t)&base, FKIOCTL, kcred, 0);
    990 		break;
    991 	}
    992 	case ARC_INTELAGP:
    993 	{
    994 		uint32_t addr;
    995 		addr = (uint32_t)phy_base;
    996 
    997 		ASSERT((phy_base & GTT_POINTER_MASK) == 0);
    998 		hdl = agp_regdev->agprd_targethdl;
    999 		err = ldi_ioctl(hdl, AGP_TARGET_SET_GATTADDR,
   1000 		    (intptr_t)&addr, FKIOCTL, kcred, 0);
   1001 		break;
   1002 	}
   1003 	case ARC_AMD64AGP:
   1004 	{
   1005 		uint32_t addr;
   1006 
   1007 		ASSERT((phy_base & AMD64_POINTER_MASK) == 0);
   1008 		addr = (uint32_t)((phy_base >> AMD64_GARTBASE_SHIFT)
   1009 		    & AMD64_GARTBASE_MASK);
   1010 
   1011 		for (gart_list = agp_regdev->agprd_cpugarts.gart_dev_list_head;
   1012 		    gart_list;
   1013 		    gart_list = gart_list->next) {
   1014 			hdl = gart_list->gart_devhdl;
   1015 			if (ldi_ioctl(hdl, AMD64_SET_GART_ADDR,
   1016 			    (intptr_t)&addr, FKIOCTL, kcred, 0)) {
   1017 				err = -1;
   1018 				break;
   1019 			}
   1020 		}
   1021 		break;
   1022 	}
   1023 	default:
   1024 		err = -1;
   1025 	}
   1026 
   1027 	if (err)
   1028 		return (-1);
   1029 
   1030 	return (0);
   1031 }
   1032 
   1033 int
   1034 lyr_set_agp_cmd(uint32_t cmd, agp_registered_dev_t *agp_regdev)
   1035 {
   1036 	ldi_handle_t hdl;
   1037 	uint32_t command;
   1038 
   1039 	ASSERT(agp_regdev);
   1040 	command = cmd;
   1041 	hdl = agp_regdev->agprd_targethdl;
   1042 	if (ldi_ioctl(hdl, AGP_TARGET_SETCMD,
   1043 	    (intptr_t)&command, FKIOCTL, kcred, 0))
   1044 		return (-1);
   1045 	hdl = agp_regdev->agprd_masterhdl;
   1046 	if (ldi_ioctl(hdl, AGP_MASTER_SETCMD,
   1047 	    (intptr_t)&command, FKIOCTL, kcred, 0))
   1048 		return (-1);
   1049 
   1050 	return (0);
   1051 }
   1052 
   1053 int
   1054 lyr_config_devices(agp_registered_dev_t *agp_regdev)
   1055 {
   1056 	amd64_gart_dev_list_t	*gart_list;
   1057 	ldi_handle_t		hdl;
   1058 	int			rc = 0;
   1059 
   1060 	ASSERT(agp_regdev);
   1061 	switch (agp_regdev->agprd_arctype) {
   1062 	case ARC_IGD830:
   1063 	case ARC_IGD810:
   1064 		break;
   1065 	case ARC_INTELAGP:
   1066 	{
   1067 		hdl = agp_regdev->agprd_targethdl;
   1068 		rc = ldi_ioctl(hdl, AGP_TARGET_CONFIGURE,
   1069 		    0, FKIOCTL, kcred, 0);
   1070 		break;
   1071 	}
   1072 	case ARC_AMD64AGP:
   1073 	{
   1074 		/*
   1075 		 * BIOS always shadow registers such like Aperture Base
   1076 		 * register, Aperture Size Register from the AGP bridge
   1077 		 * to the AMD64 CPU host bridge. If future BIOSes are broken
   1078 		 * in this regard, we may need to shadow these registers
   1079 		 * in driver.
   1080 		 */
   1081 
   1082 		for (gart_list = agp_regdev->agprd_cpugarts.gart_dev_list_head;
   1083 		    gart_list;
   1084 		    gart_list = gart_list->next) {
   1085 			hdl = gart_list->gart_devhdl;
   1086 			if (ldi_ioctl(hdl, AMD64_CONFIGURE,
   1087 			    0, FKIOCTL, kcred, 0)) {
   1088 				rc = -1;
   1089 				break;
   1090 			}
   1091 		}
   1092 		break;
   1093 	}
   1094 	default:
   1095 		rc = -1;
   1096 	}
   1097 
   1098 	if (rc)
   1099 		return (-1);
   1100 
   1101 	return (0);
   1102 }
   1103 
   1104 int
   1105 lyr_unconfig_devices(agp_registered_dev_t *agp_regdev)
   1106 {
   1107 	amd64_gart_dev_list_t	*gart_list;
   1108 	ldi_handle_t		hdl;
   1109 	int			rc = 0;
   1110 
   1111 	ASSERT(agp_regdev);
   1112 	switch (agp_regdev->agprd_arctype) {
   1113 	case ARC_IGD830:
   1114 	case ARC_IGD810:
   1115 	{
   1116 		hdl = agp_regdev->agprd_masterhdl;
   1117 		rc = ldi_ioctl(hdl, I8XX_UNCONFIG, 0, FKIOCTL, kcred, 0);
   1118 		break;
   1119 	}
   1120 	case ARC_INTELAGP:
   1121 	{
   1122 		hdl = agp_regdev->agprd_targethdl;
   1123 		rc = ldi_ioctl(hdl, AGP_TARGET_UNCONFIG,
   1124 		    0, FKIOCTL, kcred, 0);
   1125 		break;
   1126 	}
   1127 	case ARC_AMD64AGP:
   1128 	{
   1129 		for (gart_list = agp_regdev->agprd_cpugarts.gart_dev_list_head;
   1130 		    gart_list; gart_list = gart_list->next) {
   1131 			hdl = gart_list->gart_devhdl;
   1132 			if (ldi_ioctl(hdl, AMD64_UNCONFIG,
   1133 			    0, FKIOCTL, kcred, 0)) {
   1134 				rc = -1;
   1135 				break;
   1136 			}
   1137 		}
   1138 		break;
   1139 	}
   1140 	default:
   1141 		rc = -1;
   1142 	}
   1143 
   1144 	if (rc)
   1145 		return (-1);
   1146 
   1147 	return (0);
   1148 }
   1149 
   1150 /*
   1151  * lyr_flush_gart_cache()
   1152  *
   1153  * Description:
   1154  * 	This function flushes the GART translation look-aside buffer. All
   1155  * 	GART translation caches will be flushed after this operation.
   1156  *
   1157  * Arguments:
   1158  *	agp_regdev	AGP devices struct pointer
   1159  */
   1160 void
   1161 lyr_flush_gart_cache(agp_registered_dev_t *agp_regdev)
   1162 {
   1163 	amd64_gart_dev_list_t	*gart_list;
   1164 	ldi_handle_t		hdl;
   1165 
   1166 	ASSERT(agp_regdev);
   1167 	if (agp_regdev->agprd_arctype == ARC_AMD64AGP) {
   1168 		for (gart_list = agp_regdev->agprd_cpugarts.gart_dev_list_head;
   1169 		    gart_list; gart_list = gart_list->next) {
   1170 			hdl = gart_list->gart_devhdl;
   1171 			(void) ldi_ioctl(hdl, AMD64_FLUSH_GTLB,
   1172 			    0, FKIOCTL, kcred, 0);
   1173 		}
   1174 	} else if (agp_regdev->agprd_arctype == ARC_INTELAGP) {
   1175 		hdl = agp_regdev->agprd_targethdl;
   1176 		(void) ldi_ioctl(hdl, AGP_TARGET_FLUSH_GTLB, 0,
   1177 		    FKIOCTL, kcred, 0);
   1178 	}
   1179 }
   1180 
   1181 /*
   1182  * get_max_pages()
   1183  *
   1184  * Description:
   1185  * 	This function compute the total pages allowed for agp aperture
   1186  *	based on the ammount of physical pages.
   1187  * 	The algorithm is: compare the aperture size with 1/4 of total
   1188  *	physical pages, and use the smaller one to for the max available
   1189  * 	pages. But the minimum video memory should be 192M.
   1190  *
   1191  * Arguments:
   1192  * 	aper_size	system agp aperture size (in MB)
   1193  *
   1194  * Returns:
   1195  * 	The max possible number of agp memory pages available to users
   1196  */
   1197 static uint32_t
   1198 get_max_pages(uint32_t aper_size)
   1199 {
   1200 	uint32_t i, j, size;
   1201 
   1202 	ASSERT(aper_size <= MAXAPERMEGAS);
   1203 
   1204 	i = AGP_MB2PAGES(aper_size);
   1205 	j = (physmem >> 2);
   1206 
   1207 	size = ((i < j) ? i : j);
   1208 
   1209 	if (size < AGP_MB2PAGES(MINAPERMEGAS))
   1210 		size = AGP_MB2PAGES(MINAPERMEGAS);
   1211 	return (size);
   1212 }
   1213 
   1214 /*
   1215  * agp_fill_empty_keyent()
   1216  *
   1217  * Description:
   1218  * 	This function finds a empty key table slot and
   1219  * 	fills it with a new entity.
   1220  *
   1221  * Arguments:
   1222  * 	softsate	driver soft state pointer
   1223  * 	entryp		new entity data pointer
   1224  *
   1225  * Returns:
   1226  * 	NULL	no key table slot available
   1227  * 	entryp	the new entity slot pointer
   1228  */
   1229 static keytable_ent_t *
   1230 agp_fill_empty_keyent(agpgart_softstate_t *softstate, keytable_ent_t *entryp)
   1231 {
   1232 	int key;
   1233 	keytable_ent_t *newentryp;
   1234 
   1235 	ASSERT(softstate);
   1236 	ASSERT(entryp);
   1237 	ASSERT(entryp->kte_memhdl);
   1238 	ASSERT(entryp->kte_pfnarray);
   1239 	ASSERT(mutex_owned(&softstate->asoft_instmutex));
   1240 
   1241 	for (key = 0; key < AGP_MAXKEYS; key++) {
   1242 		newentryp = &softstate->asoft_table[key];
   1243 		if (newentryp->kte_memhdl == NULL) {
   1244 			break;
   1245 		}
   1246 	}
   1247 
   1248 	if (key >= AGP_MAXKEYS) {
   1249 		AGPDB_PRINT2((CE_WARN,
   1250 		    "agp_fill_empty_keyent: key table exhausted"));
   1251 		return (NULL);
   1252 	}
   1253 
   1254 	ASSERT(newentryp->kte_pfnarray == NULL);
   1255 	bcopy(entryp, newentryp, sizeof (keytable_ent_t));
   1256 	newentryp->kte_key = key;
   1257 
   1258 	return (newentryp);
   1259 }
   1260 
   1261 /*
   1262  * agp_find_bound_keyent()
   1263  *
   1264  * Description:
   1265  * 	This function finds the key table entity by agp aperture page offset.
   1266  * 	Every keytable entity will have an agp aperture range after the binding
   1267  *	operation.
   1268  *
   1269  * Arguments:
   1270  * 	softsate	driver soft state pointer
   1271  * 	pg_offset	agp aperture page offset
   1272  *
   1273  * Returns:
   1274  * 	NULL		no such keytable entity
   1275  * 	pointer		key table entity pointer found
   1276  */
   1277 static keytable_ent_t *
   1278 agp_find_bound_keyent(agpgart_softstate_t *softstate, uint32_t pg_offset)
   1279 {
   1280 	int keycount;
   1281 	keytable_ent_t *entryp;
   1282 
   1283 	ASSERT(softstate);
   1284 	ASSERT(mutex_owned(&softstate->asoft_instmutex));
   1285 
   1286 	for (keycount = 0; keycount < AGP_MAXKEYS; keycount++) {
   1287 		entryp = &softstate->asoft_table[keycount];
   1288 		if (entryp->kte_bound == 0) {
   1289 			continue;
   1290 		}
   1291 
   1292 		if (pg_offset < entryp->kte_pgoff)
   1293 			continue;
   1294 		if (pg_offset >= (entryp->kte_pgoff + entryp->kte_pages))
   1295 			continue;
   1296 
   1297 		ASSERT(entryp->kte_memhdl);
   1298 		ASSERT(entryp->kte_pfnarray);
   1299 
   1300 		return (entryp);
   1301 	}
   1302 
   1303 	return (NULL);
   1304 }
   1305 
   1306 /*
   1307  * agp_check_off()
   1308  *
   1309  * Description:
   1310  * 	This function checks whether an AGP aperture range to be bound
   1311  *	overlaps with AGP offset already bound.
   1312  *
   1313  * Arguments:
   1314  *	entryp		key table start entry pointer
   1315  * 	pg_start	AGP range start page offset
   1316  *	pg_num		pages number to be bound
   1317  *
   1318  * Returns:
   1319  *	0		Does not overlap
   1320  *	-1		Overlaps
   1321  */
   1322 
   1323 static int
   1324 agp_check_off(keytable_ent_t *entryp, uint32_t pg_start, uint32_t pg_num)
   1325 {
   1326 	int key;
   1327 	uint64_t pg_end;
   1328 	uint64_t kpg_end;
   1329 
   1330 	ASSERT(entryp);
   1331 
   1332 	pg_end = pg_start + pg_num;
   1333 	for (key = 0; key < AGP_MAXKEYS; key++) {
   1334 		if (!entryp[key].kte_bound)
   1335 			continue;
   1336 
   1337 		kpg_end = entryp[key].kte_pgoff + entryp[key].kte_pages;
   1338 		if (!((pg_end <= entryp[key].kte_pgoff) ||
   1339 		    (pg_start >= kpg_end)))
   1340 			break;
   1341 	}
   1342 
   1343 	if (key == AGP_MAXKEYS)
   1344 		return (0);
   1345 	else
   1346 		return (-1);
   1347 }
   1348 
   1349 static int
   1350 is_controlling_proc(agpgart_softstate_t *st)
   1351 {
   1352 	ASSERT(st);
   1353 
   1354 	if (!st->asoft_acquired) {
   1355 		AGPDB_PRINT2((CE_WARN,
   1356 		    "ioctl_agpgart_setup: gart not acquired"));
   1357 		return (-1);
   1358 	}
   1359 	if (st->asoft_curpid != ddi_get_pid()) {
   1360 		AGPDB_PRINT2((CE_WARN,
   1361 		    "ioctl_agpgart_release: not  controlling process"));
   1362 		return (-1);
   1363 	}
   1364 
   1365 	return (0);
   1366 }
   1367 
   1368 static void release_control(agpgart_softstate_t *st)
   1369 {
   1370 	st->asoft_curpid = 0;
   1371 	st->asoft_acquired = 0;
   1372 }
   1373 
   1374 static void acquire_control(agpgart_softstate_t *st)
   1375 {
   1376 	st->asoft_curpid = ddi_get_pid();
   1377 	st->asoft_acquired = 1;
   1378 }
   1379 
   1380 /*
   1381  * agp_remove_from_gart()
   1382  *
   1383  * Description:
   1384  * 	This function fills the gart table entries by a given page
   1385  * 	frame number array and setup the agp aperture page to physical
   1386  * 	memory page translation.
   1387  * Arguments:
   1388  * 	pg_offset	Starting aperture page to be bound
   1389  * 	entries		the number of pages to be bound
   1390  * 	acc_hdl		GART table dma memory acc handle
   1391  * 	tablep		GART table kernel virtual address
   1392  */
   1393 static void
   1394 agp_remove_from_gart(
   1395     uint32_t pg_offset,
   1396     uint32_t entries,
   1397     ddi_dma_handle_t dma_hdl,
   1398     uint32_t *tablep)
   1399 {
   1400 	uint32_t items = 0;
   1401 	uint32_t *entryp;
   1402 
   1403 	entryp = tablep + pg_offset;
   1404 	while (items < entries) {
   1405 		*(entryp + items) = 0;
   1406 		items++;
   1407 	}
   1408 	(void) ddi_dma_sync(dma_hdl, pg_offset * sizeof (uint32_t),
   1409 	    entries * sizeof (uint32_t), DDI_DMA_SYNC_FORDEV);
   1410 }
   1411 
   1412 /*
   1413  * agp_unbind_key()
   1414  *
   1415  * Description:
   1416  * 	This function unbinds AGP memory from the gart table. It will clear
   1417  * 	all the gart entries related to this agp memory.
   1418  *
   1419  * Arguments:
   1420  * 	softstate		driver soft state pointer
   1421  * 	entryp			key table entity pointer
   1422  *
   1423  * Returns:
   1424  * 	EINVAL		invalid key table entity pointer
   1425  * 	0		success
   1426  *
   1427  */
   1428 static int
   1429 agp_unbind_key(agpgart_softstate_t *softstate, keytable_ent_t *entryp)
   1430 {
   1431 	int retval = 0;
   1432 
   1433 	ASSERT(entryp);
   1434 	ASSERT((entryp->kte_key >= 0) && (entryp->kte_key < AGP_MAXKEYS));
   1435 
   1436 	if (!entryp->kte_bound) {
   1437 		AGPDB_PRINT2((CE_WARN,
   1438 		    "agp_unbind_key: key = 0x%x, not bound",
   1439 		    entryp->kte_key));
   1440 		return (EINVAL);
   1441 	}
   1442 	if (entryp->kte_refcnt) {
   1443 		AGPDB_PRINT2((CE_WARN,
   1444 		    "agp_unbind_key: memory is exported to users"));
   1445 		return (EINVAL);
   1446 	}
   1447 
   1448 	ASSERT((entryp->kte_pgoff + entryp->kte_pages) <=
   1449 	    AGP_MB2PAGES(softstate->asoft_info.agpki_apersize));
   1450 	ASSERT((softstate->asoft_devreg.agprd_arctype != ARC_UNKNOWN));
   1451 
   1452 	switch (softstate->asoft_devreg.agprd_arctype) {
   1453 	case ARC_IGD810:
   1454 	case ARC_IGD830:
   1455 		retval = lyr_i8xx_remove_from_gtt(
   1456 		    entryp->kte_pgoff, entryp->kte_pages,
   1457 		    &softstate->asoft_devreg);
   1458 		if (retval) {
   1459 			AGPDB_PRINT2((CE_WARN,
   1460 			    "agp_unbind_key: Key = 0x%x, clear table error",
   1461 			    entryp->kte_key));
   1462 			return (EIO);
   1463 		}
   1464 		break;
   1465 	case ARC_INTELAGP:
   1466 	case ARC_AMD64AGP:
   1467 		agp_remove_from_gart(entryp->kte_pgoff,
   1468 		    entryp->kte_pages,
   1469 		    softstate->gart_dma_handle,
   1470 		    (uint32_t *)softstate->gart_vbase);
   1471 		/* Flush GTLB table */
   1472 		lyr_flush_gart_cache(&softstate->asoft_devreg);
   1473 
   1474 		break;
   1475 	}
   1476 
   1477 	entryp->kte_bound = 0;
   1478 
   1479 	return (0);
   1480 }
   1481 
   1482 /*
   1483  * agp_dealloc_kmem()
   1484  *
   1485  * Description:
   1486  * 	This function deallocates dma memory resources for userland
   1487  * 	applications.
   1488  *
   1489  * Arguments:
   1490  * 	entryp		keytable entity pointer
   1491  */
   1492 static void
   1493 agp_dealloc_kmem(keytable_ent_t *entryp)
   1494 {
   1495 	kmem_free(entryp->kte_pfnarray, sizeof (pfn_t) * entryp->kte_pages);
   1496 	entryp->kte_pfnarray = NULL;
   1497 
   1498 	(void) ddi_dma_unbind_handle(KMEMP(entryp->kte_memhdl)->kmem_handle);
   1499 	KMEMP(entryp->kte_memhdl)->kmem_cookies_num = 0;
   1500 	ddi_dma_mem_free(&KMEMP(entryp->kte_memhdl)->kmem_acchdl);
   1501 	KMEMP(entryp->kte_memhdl)->kmem_acchdl = NULL;
   1502 	KMEMP(entryp->kte_memhdl)->kmem_reallen = 0;
   1503 	KMEMP(entryp->kte_memhdl)->kmem_kvaddr = NULL;
   1504 
   1505 	ddi_dma_free_handle(&(KMEMP(entryp->kte_memhdl)->kmem_handle));
   1506 	KMEMP(entryp->kte_memhdl)->kmem_handle = NULL;
   1507 
   1508 	kmem_free(entryp->kte_memhdl, sizeof (agp_kmem_handle_t));
   1509 	entryp->kte_memhdl = NULL;
   1510 }
   1511 
   1512 /*
   1513  * agp_dealloc_mem()
   1514  *
   1515  * Description:
   1516  * 	This function deallocates physical memory resources allocated for
   1517  *	userland applications.
   1518  *
   1519  * Arguments:
   1520  * 	st		driver soft state pointer
   1521  * 	entryp		key table entity pointer
   1522  *
   1523  * Returns:
   1524  * 	-1		not a valid memory type or the memory is mapped by
   1525  * 			user area applications
   1526  * 	0		success
   1527  */
   1528 static int
   1529 agp_dealloc_mem(agpgart_softstate_t *st, keytable_ent_t	*entryp)
   1530 {
   1531 
   1532 	ASSERT(entryp);
   1533 	ASSERT(st);
   1534 	ASSERT(entryp->kte_memhdl);
   1535 	ASSERT(mutex_owned(&st->asoft_instmutex));
   1536 
   1537 	/* auto unbind here */
   1538 	if (entryp->kte_bound && !entryp->kte_refcnt) {
   1539 		AGPDB_PRINT2((CE_WARN,
   1540 		    "agp_dealloc_mem: key=0x%x, auto unbind",
   1541 		    entryp->kte_key));
   1542 
   1543 		/*
   1544 		 * agp_dealloc_mem may be called indirectly by agp_detach.
   1545 		 * In the agp_detach function, agpgart_close is already
   1546 		 * called which will free the gart table. agp_unbind_key
   1547 		 * will panic if no valid gart table exists. So test if
   1548 		 * gart table exsits here.
   1549 		 */
   1550 		if (st->asoft_opened)
   1551 			(void) agp_unbind_key(st, entryp);
   1552 	}
   1553 	if (entryp->kte_refcnt) {
   1554 		AGPDB_PRINT2((CE_WARN,
   1555 		    "agp_dealloc_mem: memory is exported to users"));
   1556 		return (-1);
   1557 	}
   1558 
   1559 	switch (entryp->kte_type) {
   1560 	case AGP_NORMAL:
   1561 	case AGP_PHYSICAL:
   1562 		agp_dealloc_kmem(entryp);
   1563 		break;
   1564 	default:
   1565 		return (-1);
   1566 	}
   1567 
   1568 	return (0);
   1569 }
   1570 
   1571 /*
   1572  * agp_del_allkeys()
   1573  *
   1574  * Description:
   1575  * 	This function calls agp_dealloc_mem to release all the agp memory
   1576  *	resource allocated.
   1577  *
   1578  * Arguments:
   1579  * 	softsate	driver soft state pointer
   1580  * Returns:
   1581  * 	-1		can not free all agp memory
   1582  * 	0		success
   1583  *
   1584  */
   1585 static int
   1586 agp_del_allkeys(agpgart_softstate_t *softstate)
   1587 {
   1588 	int key;
   1589 	int ret = 0;
   1590 
   1591 	ASSERT(softstate);
   1592 	for (key = 0; key < AGP_MAXKEYS; key++) {
   1593 		if (softstate->asoft_table[key].kte_memhdl != NULL) {
   1594 			/*
   1595 			 * Check if we can free agp memory now.
   1596 			 * If agp memory is exported to user
   1597 			 * applications, agp_dealloc_mem will fail.
   1598 			 */
   1599 			if (agp_dealloc_mem(softstate,
   1600 			    &softstate->asoft_table[key]))
   1601 				ret = -1;
   1602 		}
   1603 	}
   1604 
   1605 	return (ret);
   1606 }
   1607 
   1608 /*
   1609  * pfn2gartentry()
   1610  *
   1611  * Description:
   1612  *	This function converts a physical address to GART entry.
   1613  *	For AMD64, hardware only support addresses below 40bits,
   1614  *	about 1024G physical address, so the largest pfn
   1615  *	number is below 28 bits. Please refer to GART and GTT entry
   1616  *	format table in agpdefs.h for entry format. Intel IGD only
   1617  * 	only supports GTT entry below 1G. Intel AGP only supports
   1618  * 	GART entry below 4G.
   1619  *
   1620  * Arguments:
   1621  * 	arc_type		system agp arc type
   1622  * 	pfn			page frame number
   1623  * 	itemv			the entry item to be returned
   1624  * Returns:
   1625  * 	-1			not a invalid page frame
   1626  * 	0			conversion success
   1627  */
   1628 static int
   1629 pfn2gartentry(agp_arc_type_t arc_type, pfn_t pfn, uint32_t *itemv)
   1630 {
   1631 	uint64_t paddr;
   1632 
   1633 	paddr = (uint64_t)pfn << AGP_PAGE_SHIFT;
   1634 	AGPDB_PRINT1((CE_NOTE, "checking pfn number %lu for type %d",
   1635 	    pfn, arc_type));
   1636 
   1637 	switch (arc_type) {
   1638 	case ARC_INTELAGP:
   1639 	{
   1640 		/* Only support 32-bit hardware address */
   1641 		if ((paddr & AGP_INTEL_POINTER_MASK) != 0) {
   1642 			AGPDB_PRINT2((CE_WARN,
   1643 			    "INTEL AGP Hardware only support 32 bits"));
   1644 			return (-1);
   1645 		}
   1646 		*itemv =  (pfn << AGP_PAGE_SHIFT) | AGP_ENTRY_VALID;
   1647 
   1648 		break;
   1649 	}
   1650 	case ARC_AMD64AGP:
   1651 	{
   1652 		uint32_t value1, value2;
   1653 		/* Physaddr should not exceed 40-bit */
   1654 		if ((paddr & AMD64_POINTER_MASK) != 0) {
   1655 			AGPDB_PRINT2((CE_WARN,
   1656 			    "AMD64 GART hardware only supoort 40 bits"));
   1657 			return (-1);
   1658 		}
   1659 		value1 = (uint32_t)pfn >> 20;
   1660 		value1 <<= 4;
   1661 		value2 = (uint32_t)pfn << 12;
   1662 
   1663 		*itemv = value1 | value2 | AMD64_ENTRY_VALID;
   1664 		break;
   1665 	}
   1666 	case ARC_IGD810:
   1667 		if ((paddr & I810_POINTER_MASK) != 0) {
   1668 			AGPDB_PRINT2((CE_WARN,
   1669 			    "Intel i810 only support 30 bits"));
   1670 			return (-1);
   1671 		}
   1672 		break;
   1673 
   1674 	case ARC_IGD830:
   1675 		if ((paddr & GTT_POINTER_MASK) != 0) {
   1676 			AGPDB_PRINT2((CE_WARN,
   1677 			    "Intel IGD only support 32 bits"));
   1678 			return (-1);
   1679 		}
   1680 		break;
   1681 	default:
   1682 		AGPDB_PRINT2((CE_WARN,
   1683 		    "pfn2gartentry: arc type = %d, not support", arc_type));
   1684 		return (-1);
   1685 	}
   1686 	return (0);
   1687 }
   1688 
   1689 /*
   1690  * Check allocated physical pages validity, only called in DEBUG
   1691  * mode.
   1692  */
   1693 static int
   1694 agp_check_pfns(agp_arc_type_t arc_type, pfn_t *pfnarray, int items)
   1695 {
   1696 	int count;
   1697 	uint32_t ret;
   1698 
   1699 	for (count = 0; count < items; count++) {
   1700 		if (pfn2gartentry(arc_type, pfnarray[count], &ret))
   1701 			break;
   1702 	}
   1703 	if (count < items)
   1704 		return (-1);
   1705 	else
   1706 		return (0);
   1707 }
   1708 
   1709 /*
   1710  * kmem_getpfns()
   1711  *
   1712  * Description:
   1713  * 	This function gets page frame numbers from dma handle.
   1714  *
   1715  * Arguments:
   1716  * 	dma_handle		dma hanle allocated by ddi_dma_alloc_handle
   1717  * 	dma_cookip		dma cookie pointer
   1718  * 	cookies_num		cookies number
   1719  * 	pfnarray		array to store page frames
   1720  *
   1721  * Returns:
   1722  *	0		success
   1723  */
   1724 static int
   1725 kmem_getpfns(
   1726     ddi_dma_handle_t dma_handle,
   1727     ddi_dma_cookie_t *dma_cookiep,
   1728     int cookies_num,
   1729     pfn_t *pfnarray)
   1730 {
   1731 	int	num_cookies;
   1732 	int	index = 0;
   1733 
   1734 	num_cookies = cookies_num;
   1735 
   1736 	while (num_cookies > 0) {
   1737 		uint64_t ck_startaddr, ck_length, ck_end;
   1738 		ck_startaddr = dma_cookiep->dmac_address;
   1739 		ck_length = dma_cookiep->dmac_size;
   1740 
   1741 		ck_end = ck_startaddr + ck_length;
   1742 		while (ck_startaddr < ck_end) {
   1743 			pfnarray[index] = (pfn_t)ck_startaddr >> AGP_PAGE_SHIFT;
   1744 			ck_startaddr += AGP_PAGE_SIZE;
   1745 			index++;
   1746 		}
   1747 
   1748 		num_cookies--;
   1749 		if (num_cookies > 0) {
   1750 			ddi_dma_nextcookie(dma_handle, dma_cookiep);
   1751 		}
   1752 	}
   1753 
   1754 	return (0);
   1755 }
   1756 
   1757 static int
   1758 copyinfo(agpgart_softstate_t *softstate, agp_info_t *info)
   1759 {
   1760 	switch (softstate->asoft_devreg.agprd_arctype) {
   1761 	case ARC_IGD810:
   1762 	case ARC_IGD830:
   1763 		info->agpi_version.agpv_major = 0;
   1764 		info->agpi_version.agpv_minor = 0;
   1765 		info->agpi_devid = softstate->asoft_info.agpki_mdevid;
   1766 		info->agpi_mode = 0;
   1767 		break;
   1768 	case ARC_INTELAGP:
   1769 	case ARC_AMD64AGP:
   1770 		info->agpi_version = softstate->asoft_info.agpki_tver;
   1771 		info->agpi_devid = softstate->asoft_info.agpki_tdevid;
   1772 		info->agpi_mode = softstate->asoft_info.agpki_tstatus;
   1773 		break;
   1774 	default:
   1775 		AGPDB_PRINT2((CE_WARN, "copyinfo: UNKNOW ARC"));
   1776 		return (-1);
   1777 	}
   1778 	/*
   1779 	 * 64bit->32bit conversion possible
   1780 	 */
   1781 	info->agpi_aperbase = softstate->asoft_info.agpki_aperbase;
   1782 	info->agpi_apersize = softstate->asoft_info.agpki_apersize;
   1783 	info->agpi_pgtotal = softstate->asoft_pgtotal;
   1784 	info->agpi_pgsystem = info->agpi_pgtotal;
   1785 	info->agpi_pgused = softstate->asoft_pgused;
   1786 
   1787 	return (0);
   1788 }
   1789 
   1790 static uint32_t
   1791 agp_v2_setup(uint32_t tstatus, uint32_t mstatus, uint32_t mode)
   1792 {
   1793 	uint32_t cmd;
   1794 	int rq, sba, over4g, fw, rate;
   1795 
   1796 	/*
   1797 	 * tstatus: target device status
   1798 	 * mstatus: master device status
   1799 	 * mode: the agp mode to be sent
   1800 	 */
   1801 
   1802 	/*
   1803 	 * RQ - Request Queue size
   1804 	 * set RQ to the min of mode and tstatus
   1805 	 * if mode set a RQ larger than hardware can support,
   1806 	 * use the max RQ which hardware can support.
   1807 	 * tstatus & AGPSTAT_RQ_MASK is the max RQ hardware can support
   1808 	 * Corelogic will enqueue agp transaction
   1809 	 */
   1810 	rq = mode & AGPSTAT_RQ_MASK;
   1811 	if ((tstatus & AGPSTAT_RQ_MASK) < rq)
   1812 		rq = tstatus & AGPSTAT_RQ_MASK;
   1813 
   1814 	/*
   1815 	 * SBA - Sideband Addressing
   1816 	 *
   1817 	 * Sideband Addressing provides an additional bus to pass requests
   1818 	 * (address and command) to the target from the master.
   1819 	 *
   1820 	 * set SBA if all three support it
   1821 	 */
   1822 	sba = (tstatus & AGPSTAT_SBA) & (mstatus & AGPSTAT_SBA)
   1823 	    & (mode & AGPSTAT_SBA);
   1824 
   1825 	/* set OVER4G  if all three support it */
   1826 	over4g = (tstatus & AGPSTAT_OVER4G) & (mstatus & AGPSTAT_OVER4G)
   1827 	    & (mode & AGPSTAT_OVER4G);
   1828 
   1829 	/*
   1830 	 * FW - fast write
   1831 	 *
   1832 	 * acceleration of memory write transactions from the corelogic to the
   1833 	 * A.G.P. master device acting like a PCI target.
   1834 	 *
   1835 	 * set FW if all three support it
   1836 	 */
   1837 	fw = (tstatus & AGPSTAT_FW) & (mstatus & AGPSTAT_FW)
   1838 	    & (mode & AGPSTAT_FW);
   1839 
   1840 	/*
   1841 	 * figure out the max rate
   1842 	 * AGP v2 support: 4X, 2X, 1X speed
   1843 	 * status bit		meaning
   1844 	 * ---------------------------------------------
   1845 	 * 7:3			others
   1846 	 * 3			0 stand for V2 support
   1847 	 * 0:2			001:1X, 010:2X, 100:4X
   1848 	 * ----------------------------------------------
   1849 	 */
   1850 	rate = (tstatus & AGPSTAT_RATE_MASK) & (mstatus & AGPSTAT_RATE_MASK)
   1851 	    & (mode & AGPSTAT_RATE_MASK);
   1852 	if (rate & AGP2_RATE_4X)
   1853 		rate = AGP2_RATE_4X;
   1854 	else if (rate & AGP2_RATE_2X)
   1855 		rate = AGP2_RATE_2X;
   1856 	else
   1857 		rate = AGP2_RATE_1X;
   1858 
   1859 	cmd = rq | sba | over4g | fw | rate;
   1860 	/* enable agp mode */
   1861 	cmd |= AGPCMD_AGPEN;
   1862 
   1863 	return (cmd);
   1864 }
   1865 
   1866 static uint32_t
   1867 agp_v3_setup(uint32_t tstatus, uint32_t mstatus, uint32_t mode)
   1868 {
   1869 	uint32_t cmd = 0;
   1870 	uint32_t rq, arqsz, cal, sba, over4g, fw, rate;
   1871 
   1872 	/*
   1873 	 * tstatus: target device status
   1874 	 * mstatus: master device status
   1875 	 * mode: the agp mode to be set
   1876 	 */
   1877 
   1878 	/*
   1879 	 * RQ - Request Queue size
   1880 	 * Set RQ to the min of mode and tstatus
   1881 	 * If mode set a RQ larger than hardware can support,
   1882 	 * use the max RQ which hardware can support.
   1883 	 * tstatus & AGPSTAT_RQ_MASK is the max RQ hardware can support
   1884 	 * Corelogic will enqueue agp transaction;
   1885 	 */
   1886 	rq = mode & AGPSTAT_RQ_MASK;
   1887 	if ((tstatus & AGPSTAT_RQ_MASK) < rq)
   1888 		rq = tstatus & AGPSTAT_RQ_MASK;
   1889 
   1890 	/*
   1891 	 * ARQSZ - Asynchronous Request Queue size
   1892 	 * Set the value equal to tstatus.
   1893 	 * Don't allow the mode register to override values
   1894 	 */
   1895 	arqsz = tstatus & AGPSTAT_ARQSZ_MASK;
   1896 
   1897 	/*
   1898 	 * CAL - Calibration cycle
   1899 	 * Set to the min of tstatus and mstatus
   1900 	 * Don't allow override by mode register
   1901 	 */
   1902 	cal = tstatus & AGPSTAT_CAL_MASK;
   1903 	if ((mstatus & AGPSTAT_CAL_MASK) < cal)
   1904 		cal = mstatus & AGPSTAT_CAL_MASK;
   1905 
   1906 	/*
   1907 	 * SBA - Sideband Addressing
   1908 	 *
   1909 	 * Sideband Addressing provides an additional bus to pass requests
   1910 	 * (address and command) to the target from the master.
   1911 	 *
   1912 	 * SBA in agp v3.0 must be set
   1913 	 */
   1914 	sba = AGPCMD_SBAEN;
   1915 
   1916 	/* GART64B is not set since no hardware supports it now */
   1917 
   1918 	/* Set OVER4G if all three support it */
   1919 	over4g = (tstatus & AGPSTAT_OVER4G) & (mstatus & AGPSTAT_OVER4G)
   1920 	    & (mode & AGPSTAT_OVER4G);
   1921 
   1922 	/*
   1923 	 * FW - fast write
   1924 	 *
   1925 	 * Acceleration of memory write transactions from the corelogic to the
   1926 	 * A.G.P. master device acting like a PCI target.
   1927 	 *
   1928 	 * Always set FW in AGP 3.0
   1929 	 */
   1930 	fw = (tstatus & AGPSTAT_FW) & (mstatus & AGPSTAT_FW)
   1931 	    & (mode & AGPSTAT_FW);
   1932 
   1933 	/*
   1934 	 * Figure out the max rate
   1935 	 *
   1936 	 * AGP v3 support: 8X, 4X speed
   1937 	 *
   1938 	 * status bit		meaning
   1939 	 * ---------------------------------------------
   1940 	 * 7:3			others
   1941 	 * 3			1 stand for V3 support
   1942 	 * 0:2			001:4X, 010:8X, 011:4X,8X
   1943 	 * ----------------------------------------------
   1944 	 */
   1945 	rate = (tstatus & AGPSTAT_RATE_MASK) & (mstatus & AGPSTAT_RATE_MASK)
   1946 	    & (mode & AGPSTAT_RATE_MASK);
   1947 	if (rate & AGP3_RATE_8X)
   1948 		rate = AGP3_RATE_8X;
   1949 	else
   1950 		rate = AGP3_RATE_4X;
   1951 
   1952 	cmd = rq | arqsz | cal | sba | over4g | fw | rate;
   1953 	/* Enable AGP mode */
   1954 	cmd |= AGPCMD_AGPEN;
   1955 
   1956 	return (cmd);
   1957 }
   1958 
   1959 static int
   1960 agp_setup(agpgart_softstate_t *softstate, uint32_t mode)
   1961 {
   1962 	uint32_t tstatus, mstatus;
   1963 	uint32_t agp_mode;
   1964 
   1965 	tstatus = softstate->asoft_info.agpki_tstatus;
   1966 	mstatus = softstate->asoft_info.agpki_mstatus;
   1967 
   1968 	/*
   1969 	 * There are three kinds of AGP mode. AGP mode 1.0, 2.0, 3.0
   1970 	 * AGP mode 2.0 is fully compatible with AGP mode 1.0, so we
   1971 	 * only check 2.0 and 3.0 mode. AGP 3.0 device can work in
   1972 	 * two AGP 2.0 or AGP 3.0 mode. By checking AGP status register,
   1973 	 * we can get which mode it is working at. The working mode of
   1974 	 * AGP master and AGP target must be consistent. That is, both
   1975 	 * of them must work on AGP 3.0 mode or AGP 2.0 mode.
   1976 	 */
   1977 	if ((softstate->asoft_info.agpki_tver.agpv_major == 3) &&
   1978 	    (tstatus & AGPSTAT_MODE3)) {
   1979 		/* Master device should be 3.0 mode, too */
   1980 		if ((softstate->asoft_info.agpki_mver.agpv_major != 3) ||
   1981 		    ((mstatus & AGPSTAT_MODE3) == 0))
   1982 			return (EIO);
   1983 
   1984 		agp_mode = agp_v3_setup(tstatus, mstatus, mode);
   1985 		/* Write to the AGPCMD register of target and master devices */
   1986 		if (lyr_set_agp_cmd(agp_mode,
   1987 		    &softstate->asoft_devreg))
   1988 			return (EIO);
   1989 
   1990 		softstate->asoft_mode = agp_mode;
   1991 
   1992 		return (0);
   1993 	}
   1994 
   1995 	/*
   1996 	 * If agp taget device doesn't work in AGP 3.0 mode,
   1997 	 * it must work in AGP 2.0 mode. And make sure
   1998 	 * master device work in AGP 2.0 mode too
   1999 	 */
   2000 	if ((softstate->asoft_info.agpki_mver.agpv_major == 3) &&
   2001 	    (mstatus & AGPSTAT_MODE3))
   2002 		return (EIO);
   2003 
   2004 	agp_mode = agp_v2_setup(tstatus, mstatus, mode);
   2005 	if (lyr_set_agp_cmd(agp_mode, &softstate->asoft_devreg))
   2006 		return (EIO);
   2007 	softstate->asoft_mode = agp_mode;
   2008 
   2009 	return (0);
   2010 }
   2011 
   2012 /*
   2013  * agp_alloc_kmem()
   2014  *
   2015  * Description:
   2016  * 	This function allocates physical memory for userland applications
   2017  * 	by ddi interfaces. This function can also be called to allocate
   2018  *	small phsyical contiguous pages, usually tens of kilobytes.
   2019  *
   2020  * Arguments:
   2021  * 	softsate	driver soft state pointer
   2022  * 	length		memory size
   2023  *
   2024  * Returns:
   2025  * 	entryp		new keytable entity pointer
   2026  * 	NULL		no keytable slot available or no physical
   2027  *			memory available
   2028  */
   2029 static keytable_ent_t *
   2030 agp_alloc_kmem(agpgart_softstate_t *softstate, size_t length, int type)
   2031 {
   2032 	keytable_ent_t	keyentry;
   2033 	keytable_ent_t	*entryp;
   2034 	int		ret;
   2035 
   2036 	ASSERT(AGP_ALIGNED(length));
   2037 
   2038 	bzero(&keyentry, sizeof (keytable_ent_t));
   2039 
   2040 	keyentry.kte_pages = AGP_BYTES2PAGES(length);
   2041 	keyentry.kte_type = type;
   2042 
   2043 	/*
   2044 	 * Set dma_attr_sgllen to assure contiguous physical pages
   2045 	 */
   2046 	if (type == AGP_PHYSICAL)
   2047 		agpgart_dma_attr.dma_attr_sgllen = 1;
   2048 	else
   2049 		agpgart_dma_attr.dma_attr_sgllen = (int)keyentry.kte_pages;
   2050 
   2051 	/* 4k size pages */
   2052 	keyentry.kte_memhdl = kmem_zalloc(sizeof (agp_kmem_handle_t), KM_SLEEP);
   2053 
   2054 	if (ddi_dma_alloc_handle(softstate->asoft_dip,
   2055 	    &agpgart_dma_attr,
   2056 	    DDI_DMA_SLEEP, NULL,
   2057 	    &(KMEMP(keyentry.kte_memhdl)->kmem_handle))) {
   2058 		AGPDB_PRINT2((CE_WARN,
   2059 		    "agp_alloc_kmem: ddi_dma_allco_hanlde error"));
   2060 		goto err4;
   2061 	}
   2062 
   2063 	if ((ret = ddi_dma_mem_alloc(
   2064 	    KMEMP(keyentry.kte_memhdl)->kmem_handle,
   2065 	    length,
   2066 	    &gart_dev_acc_attr,
   2067 	    DDI_DMA_CONSISTENT,
   2068 	    DDI_DMA_SLEEP, NULL,
   2069 	    &KMEMP(keyentry.kte_memhdl)->kmem_kvaddr,
   2070 	    &KMEMP(keyentry.kte_memhdl)->kmem_reallen,
   2071 	    &KMEMP(keyentry.kte_memhdl)->kmem_acchdl)) != 0) {
   2072 		AGPDB_PRINT2((CE_WARN,
   2073 		    "agp_alloc_kmem: ddi_dma_mem_alloc error"));
   2074 
   2075 		goto err3;
   2076 	}
   2077 
   2078 	ret = ddi_dma_addr_bind_handle(
   2079 	    KMEMP(keyentry.kte_memhdl)->kmem_handle,
   2080 	    NULL,
   2081 	    KMEMP(keyentry.kte_memhdl)->kmem_kvaddr,
   2082 	    length,
   2083 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
   2084 	    DDI_DMA_SLEEP,
   2085 	    NULL,
   2086 	    &KMEMP(keyentry.kte_memhdl)->kmem_dcookie,
   2087 	    &KMEMP(keyentry.kte_memhdl)->kmem_cookies_num);
   2088 
   2089 	/*
   2090 	 * Even dma_attr_sgllen = 1, ddi_dma_addr_bind_handle may return more
   2091 	 * than one cookie, we check this in the if statement.
   2092 	 */
   2093 
   2094 	if ((ret != DDI_DMA_MAPPED) ||
   2095 	    ((agpgart_dma_attr.dma_attr_sgllen == 1) &&
   2096 	    (KMEMP(keyentry.kte_memhdl)->kmem_cookies_num != 1))) {
   2097 		AGPDB_PRINT2((CE_WARN,
   2098 		    "agp_alloc_kmem: can not alloc physical memory properly"));
   2099 		goto err2;
   2100 	}
   2101 
   2102 	keyentry.kte_pfnarray = (pfn_t *)kmem_zalloc(sizeof (pfn_t) *
   2103 	    keyentry.kte_pages, KM_SLEEP);
   2104 
   2105 	if (kmem_getpfns(
   2106 	    KMEMP(keyentry.kte_memhdl)->kmem_handle,
   2107 	    &KMEMP(keyentry.kte_memhdl)->kmem_dcookie,
   2108 	    KMEMP(keyentry.kte_memhdl)->kmem_cookies_num,
   2109 	    keyentry.kte_pfnarray)) {
   2110 		AGPDB_PRINT2((CE_WARN, "agp_alloc_kmem: get pfn array error"));
   2111 		goto err1;
   2112 	}
   2113 
   2114 	ASSERT(!agp_check_pfns(softstate->asoft_devreg.agprd_arctype,
   2115 	    keyentry.kte_pfnarray, keyentry.kte_pages));
   2116 	if (agp_check_pfns(softstate->asoft_devreg.agprd_arctype,
   2117 	    keyentry.kte_pfnarray, keyentry.kte_pages))
   2118 		goto err1;
   2119 	entryp = agp_fill_empty_keyent(softstate, &keyentry);
   2120 	if (!entryp) {
   2121 		AGPDB_PRINT2((CE_WARN,
   2122 		    "agp_alloc_kmem: agp_fill_empty_keyent error"));
   2123 
   2124 		goto err1;
   2125 	}
   2126 	ASSERT((entryp->kte_key >= 0) && (entryp->kte_key < AGP_MAXKEYS));
   2127 
   2128 	return (entryp);
   2129 
   2130 err1:
   2131 	kmem_free(keyentry.kte_pfnarray, sizeof (pfn_t) * keyentry.kte_pages);
   2132 	keyentry.kte_pfnarray = NULL;
   2133 	(void) ddi_dma_unbind_handle(KMEMP(keyentry.kte_memhdl)->kmem_handle);
   2134 	KMEMP(keyentry.kte_memhdl)->kmem_cookies_num = 0;
   2135 err2:
   2136 	ddi_dma_mem_free(&KMEMP(keyentry.kte_memhdl)->kmem_acchdl);
   2137 	KMEMP(keyentry.kte_memhdl)->kmem_acchdl = NULL;
   2138 	KMEMP(keyentry.kte_memhdl)->kmem_reallen = 0;
   2139 	KMEMP(keyentry.kte_memhdl)->kmem_kvaddr = NULL;
   2140 err3:
   2141 	ddi_dma_free_handle(&(KMEMP(keyentry.kte_memhdl)->kmem_handle));
   2142 	KMEMP(keyentry.kte_memhdl)->kmem_handle = NULL;
   2143 err4:
   2144 	kmem_free(keyentry.kte_memhdl, sizeof (agp_kmem_handle_t));
   2145 	keyentry.kte_memhdl = NULL;
   2146 	return (NULL);
   2147 
   2148 }
   2149 
   2150 /*
   2151  * agp_alloc_mem()
   2152  *
   2153  * Description:
   2154  * 	This function allocate physical memory for userland applications,
   2155  * 	in order to save kernel virtual space, we use the direct mapping
   2156  * 	memory interface if it is available.
   2157  *
   2158  * Arguments:
   2159  * 	st		driver soft state pointer
   2160  * 	length		memory size
   2161  * 	type		AGP_NORMAL: normal agp memory, AGP_PHISYCAL: specical
   2162  *			memory type for intel i810 IGD
   2163  *
   2164  * Returns:
   2165  * 	NULL 	Invalid memory type or can not allocate memory
   2166  * 	Keytable entry pointer returned by agp_alloc_kmem
   2167  */
   2168 static keytable_ent_t *
   2169 agp_alloc_mem(agpgart_softstate_t *st, size_t length, int type)
   2170 {
   2171 
   2172 	/*
   2173 	 * AGP_PHYSICAL type require contiguous physical pages exported
   2174 	 * to X drivers, like i810 HW cursor, ARGB cursor. the number of
   2175 	 * pages needed is usuallysmall and contiguous, 4K, 16K. So we
   2176 	 * use DDI interface to allocated such memory. And X use xsvc
   2177 	 * drivers to map this memory into its own address space.
   2178 	 */
   2179 	ASSERT(st);
   2180 
   2181 	switch (type) {
   2182 	case AGP_NORMAL:
   2183 	case AGP_PHYSICAL:
   2184 		return (agp_alloc_kmem(st, length, type));
   2185 	default:
   2186 		return (NULL);
   2187 	}
   2188 }
   2189 
   2190 /*
   2191  * free_gart_table()
   2192  *
   2193  * Description:
   2194  * 	This function frees the gart table memory allocated by driver.
   2195  * 	Must disable gart table before calling this function.
   2196  *
   2197  * Arguments:
   2198  * 	softstate		driver soft state pointer
   2199  *
   2200  */
   2201 static void
   2202 free_gart_table(agpgart_softstate_t *st)
   2203 {
   2204 
   2205 	if (st->gart_dma_handle == NULL)
   2206 		return;
   2207 
   2208 	(void) ddi_dma_unbind_handle(st->gart_dma_handle);
   2209 	ddi_dma_mem_free(&st->gart_dma_acc_handle);
   2210 	st->gart_dma_acc_handle = NULL;
   2211 	ddi_dma_free_handle(&st->gart_dma_handle);
   2212 	st->gart_dma_handle = NULL;
   2213 	st->gart_vbase = 0;
   2214 	st->gart_size = 0;
   2215 }
   2216 
   2217 /*
   2218  * alloc_gart_table()
   2219  *
   2220  * Description:
   2221  * 	This function allocates one physical continuous gart table.
   2222  * 	INTEL integrated video device except i810 have their special
   2223  * 	video bios; No need to allocate gart table for them.
   2224  *
   2225  * Arguments:
   2226  * 	st		driver soft state pointer
   2227  *
   2228  * Returns:
   2229  * 	0		success
   2230  * 	-1		can not allocate gart tabl
   2231  */
   2232 static int
   2233 alloc_gart_table(agpgart_softstate_t *st)
   2234 {
   2235 	int			num_pages;
   2236 	size_t			table_size;
   2237 	int			ret = DDI_SUCCESS;
   2238 	ddi_dma_cookie_t	cookie;
   2239 	uint32_t		num_cookies;
   2240 
   2241 	num_pages = AGP_MB2PAGES(st->asoft_info.agpki_apersize);
   2242 
   2243 	/*
   2244 	 * Only 40-bit maximum physical memory is supported by today's
   2245 	 * AGP hardware (32-bit gart tables can hold 40-bit memory addresses).
   2246 	 * No one supports 64-bit gart entries now, so the size of gart
   2247 	 * entries defaults to 32-bit though AGP3.0 specifies the possibility
   2248 	 * of 64-bit gart entries.
   2249 	 */
   2250 
   2251 	table_size = num_pages * (sizeof (uint32_t));
   2252 
   2253 	/*
   2254 	 * Only AMD64 can put gart table above 4G, 40 bits at maximum
   2255 	 */
   2256 	if (st->asoft_devreg.agprd_arctype == ARC_AMD64AGP)
   2257 		garttable_dma_attr.dma_attr_addr_hi = 0xffffffffffLL;
   2258 	else
   2259 		garttable_dma_attr.dma_attr_addr_hi = 0xffffffffU;
   2260 	/* Allocate physical continuous page frame for gart table */
   2261 	if (ret = ddi_dma_alloc_handle(st->asoft_dip,
   2262 	    &garttable_dma_attr,
   2263 	    DDI_DMA_SLEEP,
   2264 	    NULL, &st->gart_dma_handle)) {
   2265 		AGPDB_PRINT2((CE_WARN,
   2266 		    "alloc_gart_table: ddi_dma_alloc_handle failed"));
   2267 		goto err3;
   2268 	}
   2269 
   2270 	if (ret = ddi_dma_mem_alloc(st->gart_dma_handle,
   2271 	    table_size,
   2272 	    &gart_dev_acc_attr,
   2273 	    DDI_DMA_CONSISTENT,
   2274 	    DDI_DMA_SLEEP, NULL,
   2275 	    &st->gart_vbase,
   2276 	    &st->gart_size,
   2277 	    &st->gart_dma_acc_handle)) {
   2278 		AGPDB_PRINT2((CE_WARN,
   2279 		    "alloc_gart_table: ddi_dma_mem_alloc failed"));
   2280 		goto err2;
   2281 
   2282 	}
   2283 
   2284 	ret = ddi_dma_addr_bind_handle(st->gart_dma_handle,
   2285 	    NULL, st->gart_vbase,
   2286 	    table_size,
   2287 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
   2288 	    DDI_DMA_SLEEP, NULL,
   2289 	    &cookie,  &num_cookies);
   2290 
   2291 	st->gart_pbase = cookie.dmac_address;
   2292 
   2293 	if ((ret != DDI_DMA_MAPPED) || (num_cookies != 1)) {
   2294 		if (num_cookies > 1)
   2295 			(void) ddi_dma_unbind_handle(st->gart_dma_handle);
   2296 		AGPDB_PRINT2((CE_WARN,
   2297 		    "alloc_gart_table: alloc contiguous phys memory failed"));
   2298 		goto err1;
   2299 	}
   2300 
   2301 	return (0);
   2302 err1:
   2303 	ddi_dma_mem_free(&st->gart_dma_acc_handle);
   2304 	st->gart_dma_acc_handle = NULL;
   2305 err2:
   2306 	ddi_dma_free_handle(&st->gart_dma_handle);
   2307 	st->gart_dma_handle = NULL;
   2308 err3:
   2309 	st->gart_pbase = 0;
   2310 	st->gart_size = 0;
   2311 	st->gart_vbase = 0;
   2312 
   2313 	return (-1);
   2314 }
   2315 
   2316 /*
   2317  * agp_add_to_gart()
   2318  *
   2319  * Description:
   2320  * 	This function fills the gart table entries by a given page frame number
   2321  * 	array and set up the agp aperture page to physical memory page
   2322  * 	translation.
   2323  * Arguments:
   2324  * 	type		valid sytem arc types ARC_AMD64AGP, ARC_INTELAGP,
   2325  * 			ARC_AMD64AGP
   2326  * 	pfnarray	allocated physical page frame number array
   2327  * 	pg_offset	agp aperture start page to be bound
   2328  * 	entries		the number of pages to be bound
   2329  * 	dma_hdl		gart table dma memory handle
   2330  * 	tablep		gart table kernel virtual address
   2331  * Returns:
   2332  * 	-1		failed
   2333  * 	0		success
   2334  */
   2335 static int
   2336 agp_add_to_gart(
   2337     agp_arc_type_t type,
   2338     pfn_t *pfnarray,
   2339     uint32_t pg_offset,
   2340     uint32_t entries,
   2341     ddi_dma_handle_t dma_hdl,
   2342     uint32_t *tablep)
   2343 {
   2344 	int items = 0;
   2345 	uint32_t *entryp;
   2346 	uint32_t itemv;
   2347 
   2348 	entryp = tablep + pg_offset;
   2349 	while (items < entries) {
   2350 		if (pfn2gartentry(type, pfnarray[items], &itemv))
   2351 			break;
   2352 		*(entryp + items) = itemv;
   2353 		items++;
   2354 	}
   2355 	if (items < entries)
   2356 		return (-1);
   2357 
   2358 	(void) ddi_dma_sync(dma_hdl, pg_offset * sizeof (uint32_t),
   2359 	    entries * sizeof (uint32_t), DDI_DMA_SYNC_FORDEV);
   2360 
   2361 	return (0);
   2362 }
   2363 
   2364 /*
   2365  * agp_bind_key()
   2366  *
   2367  * Description:
   2368  * 	This function will call low level gart table access functions to
   2369  * 	set up gart table translation. Also it will do some sanity
   2370  * 	checking on key table entry.
   2371  *
   2372  * Arguments:
   2373  * 	softstate		driver soft state pointer
   2374  * 	keyent			key table entity pointer to be bound
   2375  * 	pg_offset		aperture start page to be bound
   2376  * Returns:
   2377  * 	EINVAL			not a valid operation
   2378  */
   2379 static int
   2380 agp_bind_key(agpgart_softstate_t *softstate,
   2381     keytable_ent_t  *keyent, uint32_t  pg_offset)
   2382 {
   2383 	uint64_t pg_end;
   2384 	int ret = 0;
   2385 
   2386 	ASSERT(keyent);
   2387 	ASSERT((keyent->kte_key >= 0) && (keyent->kte_key < AGP_MAXKEYS));
   2388 	ASSERT(mutex_owned(&softstate->asoft_instmutex));
   2389 
   2390 	pg_end = pg_offset + keyent->kte_pages;
   2391 
   2392 	if (pg_end > AGP_MB2PAGES(softstate->asoft_info.agpki_apersize)) {
   2393 		AGPDB_PRINT2((CE_WARN,
   2394 		    "agp_bind_key: key=0x%x,exceed aper range",
   2395 		    keyent->kte_key));
   2396 
   2397 		return (EINVAL);
   2398 	}
   2399 
   2400 	if (agp_check_off(softstate->asoft_table,
   2401 	    pg_offset, keyent->kte_pages)) {
   2402 		AGPDB_PRINT2((CE_WARN,
   2403 		    "agp_bind_key: pg_offset=0x%x, pages=0x%lx overlaped",
   2404 		    pg_offset, keyent->kte_pages));
   2405 		return (EINVAL);
   2406 	}
   2407 
   2408 	ASSERT(keyent->kte_pfnarray != NULL);
   2409 
   2410 	switch (softstate->asoft_devreg.agprd_arctype) {
   2411 	case ARC_IGD810:
   2412 	case ARC_IGD830:
   2413 		ret = lyr_i8xx_add_to_gtt(pg_offset, keyent,
   2414 		    &softstate->asoft_devreg);
   2415 		if (ret)
   2416 			return (EIO);
   2417 		break;
   2418 	case ARC_INTELAGP:
   2419 	case ARC_AMD64AGP:
   2420 		ret =  agp_add_to_gart(
   2421 		    softstate->asoft_devreg.agprd_arctype,
   2422 		    keyent->kte_pfnarray,
   2423 		    pg_offset,
   2424 		    keyent->kte_pages,
   2425 		    softstate->gart_dma_handle,
   2426 		    (uint32_t *)softstate->gart_vbase);
   2427 		if (ret)
   2428 			return (EINVAL);
   2429 		/* Flush GTLB table */
   2430 		lyr_flush_gart_cache(&softstate->asoft_devreg);
   2431 		break;
   2432 	default:
   2433 		AGPDB_PRINT2((CE_WARN,
   2434 		    "agp_bind_key: arc type = 0x%x unsupported",
   2435 		    softstate->asoft_devreg.agprd_arctype));
   2436 		return (EINVAL);
   2437 	}
   2438 	return (0);
   2439 }
   2440 
   2441 static int
   2442 agpgart_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
   2443 {
   2444 	int instance;
   2445 	agpgart_softstate_t *softstate;
   2446 
   2447 	if (cmd != DDI_ATTACH) {
   2448 		AGPDB_PRINT2((CE_WARN,
   2449 		    "agpgart_attach: only attach op supported"));
   2450 		return (DDI_FAILURE);
   2451 	}
   2452 	instance = ddi_get_instance(dip);
   2453 
   2454 	if (ddi_soft_state_zalloc(agpgart_glob_soft_handle, instance)
   2455 	    != DDI_SUCCESS) {
   2456 		AGPDB_PRINT2((CE_WARN,
   2457 		    "agpgart_attach: soft state zalloc failed"));
   2458 		goto err1;
   2459 
   2460 	}
   2461 	softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
   2462 	mutex_init(&softstate->asoft_instmutex, NULL, MUTEX_DRIVER, NULL);
   2463 	softstate->asoft_dip = dip;
   2464 	/*
   2465 	 * Allocate LDI identifier for agpgart driver
   2466 	 * Agpgart driver is the kernel consumer
   2467 	 */
   2468 	if (ldi_ident_from_dip(dip, &softstate->asoft_li)) {
   2469 		AGPDB_PRINT2((CE_WARN,
   2470 		    "agpgart_attach: LDI indentifier allcation failed"));
   2471 		goto err2;
   2472 	}
   2473 
   2474 	softstate->asoft_devreg.agprd_arctype = ARC_UNKNOWN;
   2475 	/* Install agp kstat */
   2476 	if (agp_init_kstats(softstate)) {
   2477 		AGPDB_PRINT2((CE_WARN, "agpgart_attach: init kstats error"));
   2478 		goto err3;
   2479 	}
   2480 	/*
   2481 	 * devfs will create /dev/agpgart
   2482 	 * and  /devices/agpgart:agpgart
   2483 	 */
   2484 
   2485 	if (ddi_create_minor_node(dip, AGPGART_DEVNODE, S_IFCHR,
   2486 	    AGP_INST2MINOR(instance),
   2487 	    DDI_NT_AGP_PSEUDO, 0)) {
   2488 		AGPDB_PRINT2((CE_WARN,
   2489 		    "agpgart_attach: Can not create minor node"));
   2490 		goto err4;
   2491 	}
   2492 
   2493 	softstate->asoft_table = kmem_zalloc(
   2494 	    AGP_MAXKEYS * (sizeof (keytable_ent_t)),
   2495 	    KM_SLEEP);
   2496 
   2497 	list_head_init(&softstate->mapped_list);
   2498 
   2499 	return (DDI_SUCCESS);
   2500 err4:
   2501 	agp_fini_kstats(softstate);
   2502 err3:
   2503 	ldi_ident_release(softstate->asoft_li);
   2504 err2:
   2505 	ddi_soft_state_free(agpgart_glob_soft_handle, instance);
   2506 err1:
   2507 	return (DDI_FAILURE);
   2508 }
   2509 
   2510 static int
   2511 agpgart_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
   2512 {
   2513 	int instance;
   2514 	agpgart_softstate_t *st;
   2515 
   2516 	instance = ddi_get_instance(dip);
   2517 
   2518 	st = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
   2519 
   2520 	if (cmd != DDI_DETACH)
   2521 		return (DDI_FAILURE);
   2522 
   2523 	/*
   2524 	 * Caller should free all the memory allocated explicitly.
   2525 	 * We release the memory allocated by caller which is not
   2526 	 * properly freed. mutex_enter here make sure assertion on
   2527 	 * softstate mutex success in agp_dealloc_mem.
   2528 	 */
   2529 	mutex_enter(&st->asoft_instmutex);
   2530 	if (agp_del_allkeys(st)) {
   2531 		AGPDB_PRINT2((CE_WARN, "agpgart_detach: agp_del_allkeys err"));
   2532 		AGPDB_PRINT2((CE_WARN,
   2533 		    "you might free agp memory exported to your applications"));
   2534 
   2535 		mutex_exit(&st->asoft_instmutex);
   2536 		return (DDI_FAILURE);
   2537 	}
   2538 	mutex_exit(&st->asoft_instmutex);
   2539 	if (st->asoft_table) {
   2540 		kmem_free(st->asoft_table,
   2541 		    AGP_MAXKEYS * (sizeof (keytable_ent_t)));
   2542 		st->asoft_table = 0;
   2543 	}
   2544 
   2545 	struct list_head	*entry,	*temp,	*head;
   2546 	igd_gtt_seg_t	*gttseg;
   2547 	list_head_for_each_safe(entry, temp, &st->mapped_list) {
   2548 		gttseg = entry->gttseg;
   2549 		list_head_del(entry);
   2550 		kmem_free(entry, sizeof (*entry));
   2551 		kmem_free(gttseg->igs_phyaddr,
   2552 		    sizeof (uint32_t) * gttseg->igs_npage);
   2553 		kmem_free(gttseg, sizeof (igd_gtt_seg_t));
   2554 	}
   2555 	head = &st->mapped_list;
   2556 	kmem_free(head->next,
   2557 	    AGP_HASH_NODE * sizeof (struct list_head));
   2558 	head->next = NULL;
   2559 
   2560 	ddi_remove_minor_node(dip, AGPGART_DEVNODE);
   2561 	agp_fini_kstats(st);
   2562 	ldi_ident_release(st->asoft_li);
   2563 	mutex_destroy(&st->asoft_instmutex);
   2564 	ddi_soft_state_free(agpgart_glob_soft_handle, instance);
   2565 
   2566 	return (DDI_SUCCESS);
   2567 }
   2568 
   2569 /*ARGSUSED*/
   2570 static int
   2571 agpgart_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
   2572     void **resultp)
   2573 {
   2574 	agpgart_softstate_t *st;
   2575 	int instance, rval = DDI_FAILURE;
   2576 	dev_t dev;
   2577 
   2578 	switch (cmd) {
   2579 	case DDI_INFO_DEVT2DEVINFO:
   2580 		dev = (dev_t)arg;
   2581 		instance = AGP_DEV2INST(dev);
   2582 		st = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
   2583 		if (st != NULL) {
   2584 			mutex_enter(&st->asoft_instmutex);
   2585 			*resultp = st->asoft_dip;
   2586 			mutex_exit(&st->asoft_instmutex);
   2587 			rval = DDI_SUCCESS;
   2588 		} else
   2589 			*resultp = NULL;
   2590 
   2591 		break;
   2592 	case DDI_INFO_DEVT2INSTANCE:
   2593 		dev = (dev_t)arg;
   2594 		instance = AGP_DEV2INST(dev);
   2595 		*resultp = (void *)(uintptr_t)instance;
   2596 		rval = DDI_SUCCESS;
   2597 
   2598 		break;
   2599 	default:
   2600 		break;
   2601 	}
   2602 
   2603 	return (rval);
   2604 }
   2605 
   2606 /*
   2607  * agpgart_open()
   2608  *
   2609  * Description:
   2610  * 	This function is the driver open entry point. If it is the
   2611  * 	first time the agpgart driver is opened, the driver will
   2612  * 	open other agp related layered drivers and set up the agpgart
   2613  * 	table properly.
   2614  *
   2615  * Arguments:
   2616  * 	dev			device number pointer
   2617  * 	openflags		open flags
   2618  *	otyp			OTYP_BLK, OTYP_CHR
   2619  * 	credp			user's credential's struct pointer
   2620  *
   2621  * Returns:
   2622  * 	ENXIO			operation error
   2623  * 	EAGAIN			resoure temporarily unvailable
   2624  * 	0			success
   2625  */
   2626 /*ARGSUSED*/
   2627 static int
   2628 agpgart_open(dev_t *dev, int openflags, int otyp, cred_t *credp)
   2629 {
   2630 	int instance = AGP_DEV2INST(*dev);
   2631 	agpgart_softstate_t *softstate;
   2632 	int rc = 0;
   2633 	uint32_t devid;
   2634 
   2635 	if (secpolicy_gart_access(credp)) {
   2636 		AGPDB_PRINT2((CE_WARN, "agpgart_open: permission denied"));
   2637 		return (EPERM);
   2638 	}
   2639 	softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
   2640 	if (softstate == NULL) {
   2641 		AGPDB_PRINT2((CE_WARN, "agpgart_open: get soft state err"));
   2642 		return (ENXIO);
   2643 	}
   2644 
   2645 	mutex_enter(&softstate->asoft_instmutex);
   2646 
   2647 	if (softstate->asoft_opened) {
   2648 		softstate->asoft_opened++;
   2649 		mutex_exit(&softstate->asoft_instmutex);
   2650 		return (0);
   2651 	}
   2652 
   2653 	/*
   2654 	 * The driver is opened first time, so we initialize layered
   2655 	 * driver interface and softstate member here.
   2656 	 */
   2657 	softstate->asoft_pgused = 0;
   2658 	if (lyr_init(&softstate->asoft_devreg, softstate->asoft_li)) {
   2659 		AGPDB_PRINT2((CE_WARN, "agpgart_open: lyr_init failed"));
   2660 		mutex_exit(&softstate->asoft_instmutex);
   2661 		return (EAGAIN);
   2662 	}
   2663 
   2664 	/* Call into layered driver */
   2665 	if (lyr_get_info(&softstate->asoft_info, &softstate->asoft_devreg)) {
   2666 		AGPDB_PRINT2((CE_WARN, "agpgart_open: lyr_get_info error"));
   2667 		lyr_end(&softstate->asoft_devreg);
   2668 		mutex_exit(&softstate->asoft_instmutex);
   2669 		return (EIO);
   2670 	}
   2671 
   2672 	/*
   2673 	 * BIOS already set up gtt table for ARC_IGD830
   2674 	 */
   2675 	if (IS_INTEL_830(softstate->asoft_devreg.agprd_arctype)) {
   2676 		softstate->asoft_opened++;
   2677 
   2678 		softstate->asoft_pgtotal =
   2679 		    get_max_pages(softstate->asoft_info.agpki_apersize);
   2680 
   2681 		if (lyr_config_devices(&softstate->asoft_devreg)) {
   2682 			AGPDB_PRINT2((CE_WARN,
   2683 			    "agpgart_open: lyr_config_devices error"));
   2684 			lyr_end(&softstate->asoft_devreg);
   2685 			mutex_exit(&softstate->asoft_instmutex);
   2686 
   2687 			return (EIO);
   2688 		}
   2689 		devid = softstate->asoft_info.agpki_mdevid;
   2690 		if (IS_INTEL_915(devid) ||
   2691 		    IS_INTEL_965(devid) ||
   2692 		    IS_INTEL_X33(devid) ||
   2693 		    IS_INTEL_G4X(devid)) {
   2694 			rc = ldi_ioctl(softstate->asoft_devreg.agprd_targethdl,
   2695 			    INTEL_CHIPSET_FLUSH_SETUP, 0, FKIOCTL, kcred, 0);
   2696 		}
   2697 		if (rc) {
   2698 			AGPDB_PRINT2((CE_WARN,
   2699 			    "agpgart_open: Intel chipset flush setup error"));
   2700 			lyr_end(&softstate->asoft_devreg);
   2701 			mutex_exit(&softstate->asoft_instmutex);
   2702 			return (EIO);
   2703 		}
   2704 		mutex_exit(&softstate->asoft_instmutex);
   2705 		return (0);
   2706 	}
   2707 
   2708 	rc = alloc_gart_table(softstate);
   2709 
   2710 	/*
   2711 	 * Allocate physically contiguous pages for AGP arc or
   2712 	 * i810 arc. If failed, divide aper_size by 2 to
   2713 	 * reduce gart table size until 4 megabytes. This
   2714 	 * is just a workaround for systems with very few
   2715 	 * physically contiguous memory.
   2716 	 */
   2717 	if (rc) {
   2718 		while ((softstate->asoft_info.agpki_apersize >= 4) &&
   2719 		    (alloc_gart_table(softstate))) {
   2720 			softstate->asoft_info.agpki_apersize >>= 1;
   2721 		}
   2722 		if (softstate->asoft_info.agpki_apersize >= 4)
   2723 			rc = 0;
   2724 	}
   2725 
   2726 	if (rc != 0) {
   2727 		AGPDB_PRINT2((CE_WARN,
   2728 		    "agpgart_open: alloc gart table failed"));
   2729 		lyr_end(&softstate->asoft_devreg);
   2730 		mutex_exit(&softstate->asoft_instmutex);
   2731 		return (EAGAIN);
   2732 	}
   2733 
   2734 	softstate->asoft_pgtotal =
   2735 	    get_max_pages(softstate->asoft_info.agpki_apersize);
   2736 	/*
   2737 	 * BIOS doesn't initialize GTT for i810,
   2738 	 * So i810 GTT must be created by driver.
   2739 	 *
   2740 	 * Set up gart table and enable it.
   2741 	 */
   2742 	if (lyr_set_gart_addr(softstate->gart_pbase,
   2743 	    &softstate->asoft_devreg)) {
   2744 		AGPDB_PRINT2((CE_WARN,
   2745 		    "agpgart_open: set gart table addr failed"));
   2746 		free_gart_table(softstate);
   2747 		lyr_end(&softstate->asoft_devreg);
   2748 		mutex_exit(&softstate->asoft_instmutex);
   2749 		return (EIO);
   2750 	}
   2751 	if (lyr_config_devices(&softstate->asoft_devreg)) {
   2752 		AGPDB_PRINT2((CE_WARN,
   2753 		    "agpgart_open: lyr_config_devices failed"));
   2754 		free_gart_table(softstate);
   2755 		lyr_end(&softstate->asoft_devreg);
   2756 		mutex_exit(&softstate->asoft_instmutex);
   2757 		return (EIO);
   2758 	}
   2759 
   2760 	softstate->asoft_opened++;
   2761 	mutex_exit(&softstate->asoft_instmutex);
   2762 
   2763 	return (0);
   2764 }
   2765 
   2766 /*
   2767  * agpgart_close()
   2768  *
   2769  * Description:
   2770  * 	agpgart_close will release resources allocated in the first open
   2771  * 	and close other open layered drivers. Also it frees the memory
   2772  *	allocated by ioctls.
   2773  *
   2774  * Arguments:
   2775  * 	dev			device number
   2776  * 	flag			file status flag
   2777  *	otyp			OTYP_BLK, OTYP_CHR
   2778  * 	credp			user's credential's struct pointer
   2779  *
   2780  * Returns:
   2781  * 	ENXIO			not an error, to support "deferred attach"
   2782  * 	0			success
   2783  */
   2784 /*ARGSUSED*/
   2785 static int
   2786 agpgart_close(dev_t dev, int flag, int otyp, cred_t *credp)
   2787 {
   2788 	int instance = AGP_DEV2INST(dev);
   2789 	agpgart_softstate_t *softstate;
   2790 	int rc = 0;
   2791 	uint32_t devid;
   2792 
   2793 	softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
   2794 	if (softstate == NULL) {
   2795 		AGPDB_PRINT2((CE_WARN, "agpgart_close: get soft state err"));
   2796 		return (ENXIO);
   2797 	}
   2798 
   2799 	mutex_enter(&softstate->asoft_instmutex);
   2800 	ASSERT(softstate->asoft_opened);
   2801 
   2802 
   2803 	/*
   2804 	 * If the last process close this device is not the controlling
   2805 	 * process, also release the control over agpgart driver here if the
   2806 	 * the controlling process fails to release the control before it
   2807 	 * close the driver.
   2808 	 */
   2809 	if (softstate->asoft_acquired == 1) {
   2810 		AGPDB_PRINT2((CE_WARN,
   2811 		    "agpgart_close: auto release control over driver"));
   2812 		release_control(softstate);
   2813 	}
   2814 
   2815 	devid = softstate->asoft_info.agpki_mdevid;
   2816 	if (IS_INTEL_915(devid) ||
   2817 	    IS_INTEL_965(devid) ||
   2818 	    IS_INTEL_X33(devid) ||
   2819 	    IS_INTEL_G4X(devid)) {
   2820 		rc = ldi_ioctl(softstate->asoft_devreg.agprd_targethdl,
   2821 		    INTEL_CHIPSET_FLUSH_FREE, 0, FKIOCTL, kcred, 0);
   2822 	}
   2823 	if (rc) {
   2824 		AGPDB_PRINT2((CE_WARN,
   2825 		    "agpgart_open: Intel chipset flush free error"));
   2826 	}
   2827 
   2828 	if (lyr_unconfig_devices(&softstate->asoft_devreg)) {
   2829 		AGPDB_PRINT2((CE_WARN,
   2830 		    "agpgart_close: lyr_unconfig_device error"));
   2831 		mutex_exit(&softstate->asoft_instmutex);
   2832 		return (EIO);
   2833 	}
   2834 	softstate->asoft_agpen = 0;
   2835 
   2836 	if (!IS_INTEL_830(softstate->asoft_devreg.agprd_arctype)) {
   2837 		free_gart_table(softstate);
   2838 	}
   2839 
   2840 	lyr_end(&softstate->asoft_devreg);
   2841 
   2842 	/*
   2843 	 * This statement must be positioned before agp_del_allkeys
   2844 	 * agp_dealloc_mem indirectly called by agp_del_allkeys
   2845 	 * will test this variable.
   2846 	 */
   2847 	softstate->asoft_opened = 0;
   2848 
   2849 	/*
   2850 	 * Free the memory allocated by user applications which
   2851 	 * was never deallocated.
   2852 	 */
   2853 	(void) agp_del_allkeys(softstate);
   2854 
   2855 	mutex_exit(&softstate->asoft_instmutex);
   2856 
   2857 	return (0);
   2858 }
   2859 
   2860 static int
   2861 ioctl_agpgart_info(agpgart_softstate_t  *softstate, void  *arg, int flags)
   2862 {
   2863 	agp_info_t infostruct;
   2864 #ifdef _MULTI_DATAMODEL
   2865 	agp_info32_t infostruct32;
   2866 #endif
   2867 
   2868 	bzero(&infostruct, sizeof (agp_info_t));
   2869 
   2870 #ifdef _MULTI_DATAMODEL
   2871 	bzero(&infostruct32, sizeof (agp_info32_t));
   2872 	if (ddi_model_convert_from(flags & FMODELS) == DDI_MODEL_ILP32) {
   2873 		if (copyinfo(softstate, &infostruct))
   2874 			return (EINVAL);
   2875 
   2876 		agpinfo_default_to_32(infostruct, infostruct32);
   2877 		if (ddi_copyout(&infostruct32, arg,
   2878 		    sizeof (agp_info32_t), flags) != 0)
   2879 			return (EFAULT);
   2880 
   2881 		return (0);
   2882 	}
   2883 #endif /* _MULTI_DATAMODEL */
   2884 	if (copyinfo(softstate, &infostruct))
   2885 		return (EINVAL);
   2886 
   2887 	if (ddi_copyout(&infostruct, arg, sizeof (agp_info_t), flags) != 0) {
   2888 		return (EFAULT);
   2889 	}
   2890 
   2891 	return (0);
   2892 }
   2893 
   2894 static int
   2895 ioctl_agpgart_acquire(agpgart_softstate_t  *st)
   2896 {
   2897 	if (st->asoft_acquired) {
   2898 		AGPDB_PRINT2((CE_WARN, "ioctl_acquire: already acquired"));
   2899 		return (EBUSY);
   2900 	}
   2901 	acquire_control(st);
   2902 	return (0);
   2903 }
   2904 
   2905 static int
   2906 ioctl_agpgart_release(agpgart_softstate_t  *st)
   2907 {
   2908 	if (is_controlling_proc(st) < 0) {
   2909 		AGPDB_PRINT2((CE_WARN,
   2910 		    "ioctl_agpgart_release: not a controlling process"));
   2911 		return (EPERM);
   2912 	}
   2913 	release_control(st);
   2914 	return (0);
   2915 }
   2916 
   2917 static int
   2918 ioctl_agpgart_setup(agpgart_softstate_t  *st, void  *arg, int flags)
   2919 {
   2920 	agp_setup_t data;
   2921 	int rc = 0;
   2922 
   2923 	if (is_controlling_proc(st) < 0) {
   2924 		AGPDB_PRINT2((CE_WARN,
   2925 		    "ioctl_agpgart_setup: not a controlling process"));
   2926 		return (EPERM);
   2927 	}
   2928 
   2929 	if (!IS_TRUE_AGP(st->asoft_devreg.agprd_arctype)) {
   2930 		AGPDB_PRINT2((CE_WARN,
   2931 		    "ioctl_agpgart_setup: no true agp bridge"));
   2932 		return (EINVAL);
   2933 	}
   2934 
   2935 	if (ddi_copyin(arg, &data, sizeof (agp_setup_t), flags) != 0)
   2936 		return (EFAULT);
   2937 
   2938 	if (rc = agp_setup(st, data.agps_mode))
   2939 		return (rc);
   2940 	/* Store agp mode status for kstat */
   2941 	st->asoft_agpen = 1;
   2942 	return (0);
   2943 }
   2944 
   2945 static int
   2946 ioctl_agpgart_alloc(agpgart_softstate_t  *st, void  *arg, int flags)
   2947 {
   2948 	agp_allocate_t	alloc_info;
   2949 	keytable_ent_t	*entryp;
   2950 	size_t		length;
   2951 	uint64_t	pg_num;
   2952 
   2953 	if (is_controlling_proc(st) < 0) {
   2954 		AGPDB_PRINT2((CE_WARN,
   2955 		    "ioctl_agpgart_alloc: not a controlling process"));
   2956 		return (EPERM);
   2957 	}
   2958 
   2959 	if (ddi_copyin(arg, &alloc_info,
   2960 	    sizeof (agp_allocate_t), flags) != 0) {
   2961 		return (EFAULT);
   2962 	}
   2963 	pg_num = st->asoft_pgused + alloc_info.agpa_pgcount;
   2964 	if (pg_num > st->asoft_pgtotal) {
   2965 		AGPDB_PRINT2((CE_WARN,
   2966 		    "ioctl_agpgart_alloc: exceeding the memory pages limit"));
   2967 		AGPDB_PRINT2((CE_WARN,
   2968 		    "ioctl_agpgart_alloc: request %x pages failed",
   2969 		    alloc_info.agpa_pgcount));
   2970 		AGPDB_PRINT2((CE_WARN,
   2971 		    "ioctl_agpgart_alloc: pages used %x total is %x",
   2972 		    st->asoft_pgused, st->asoft_pgtotal));
   2973 
   2974 		return (EINVAL);
   2975 	}
   2976 
   2977 	length = AGP_PAGES2BYTES(alloc_info.agpa_pgcount);
   2978 	entryp = agp_alloc_mem(st, length, alloc_info.agpa_type);
   2979 	if (!entryp) {
   2980 		AGPDB_PRINT2((CE_WARN,
   2981 		    "ioctl_agpgart_alloc: allocate 0x%lx bytes failed",
   2982 		    length));
   2983 		return (ENOMEM);
   2984 	}
   2985 	ASSERT((entryp->kte_key >= 0) && (entryp->kte_key < AGP_MAXKEYS));
   2986 	alloc_info.agpa_key = entryp->kte_key;
   2987 	if (alloc_info.agpa_type == AGP_PHYSICAL) {
   2988 		alloc_info.agpa_physical =
   2989 		    (uint32_t)(entryp->kte_pfnarray[0] << AGP_PAGE_SHIFT);
   2990 	}
   2991 	/* Update the memory pagse used */
   2992 	st->asoft_pgused += alloc_info.agpa_pgcount;
   2993 
   2994 	if (ddi_copyout(&alloc_info, arg,
   2995 	    sizeof (agp_allocate_t), flags) != 0) {
   2996 
   2997 		return (EFAULT);
   2998 	}
   2999 
   3000 	return (0);
   3001 }
   3002 
   3003 static int
   3004 ioctl_agpgart_dealloc(agpgart_softstate_t  *st, intptr_t arg)
   3005 {
   3006 	int key;
   3007 	keytable_ent_t  *keyent;
   3008 
   3009 	if (is_controlling_proc(st) < 0) {
   3010 		AGPDB_PRINT2((CE_WARN,
   3011 		    "ioctl_agpgart_dealloc: not a controlling process"));
   3012 		return (EPERM);
   3013 	}
   3014 	key = (int)arg;
   3015 	if ((key >= AGP_MAXKEYS) || key < 0) {
   3016 		return (EINVAL);
   3017 	}
   3018 	keyent = &st->asoft_table[key];
   3019 	if (!keyent->kte_memhdl) {
   3020 		return (EINVAL);
   3021 	}
   3022 
   3023 	if (agp_dealloc_mem(st, keyent))
   3024 		return (EINVAL);
   3025 
   3026 	/* Update the memory pages used */
   3027 	st->asoft_pgused -= keyent->kte_pages;
   3028 	bzero(keyent, sizeof (keytable_ent_t));
   3029 
   3030 	return (0);
   3031 }
   3032 
   3033 static int
   3034 ioctl_agpgart_bind(agpgart_softstate_t  *st, void  *arg, int flags)
   3035 {
   3036 	agp_bind_t 	bind_info;
   3037 	keytable_ent_t	*keyent;
   3038 	int		key;
   3039 	uint32_t	pg_offset;
   3040 	int		retval = 0;
   3041 
   3042 	if (is_controlling_proc(st) < 0) {
   3043 		AGPDB_PRINT2((CE_WARN,
   3044 		    "ioctl_agpgart_bind: not a controlling process"));
   3045 		return (EPERM);
   3046 	}
   3047 
   3048 	if (ddi_copyin(arg, &bind_info, sizeof (agp_bind_t), flags) != 0) {
   3049 		return (EFAULT);
   3050 	}
   3051 
   3052 	key = bind_info.agpb_key;
   3053 	if ((key >= AGP_MAXKEYS) || key < 0) {
   3054 		AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_bind: invalid key"));
   3055 		return (EINVAL);
   3056 	}
   3057 
   3058 	if (IS_INTEL_830(st->asoft_devreg.agprd_arctype)) {
   3059 		if (AGP_PAGES2KB(bind_info.agpb_pgstart) <
   3060 		    st->asoft_info.agpki_presize) {
   3061 			AGPDB_PRINT2((CE_WARN,
   3062 			    "ioctl_agpgart_bind: bind to prealloc area "
   3063 			    "pgstart = %dKB < presize = %ldKB",
   3064 			    AGP_PAGES2KB(bind_info.agpb_pgstart),
   3065 			    st->asoft_info.agpki_presize));
   3066 			return (EINVAL);
   3067 		}
   3068 	}
   3069 
   3070 	pg_offset = bind_info.agpb_pgstart;
   3071 	keyent = &st->asoft_table[key];
   3072 	if (!keyent->kte_memhdl) {
   3073 		AGPDB_PRINT2((CE_WARN,
   3074 		    "ioctl_agpgart_bind: Key = 0x%x can't get keyenty",
   3075 		    key));
   3076 		return (EINVAL);
   3077 	}
   3078 
   3079 	if (keyent->kte_bound != 0) {
   3080 		AGPDB_PRINT2((CE_WARN,
   3081 		    "ioctl_agpgart_bind: Key = 0x%x already bound",
   3082 		    key));
   3083 		return (EINVAL);
   3084 	}
   3085 	retval = agp_bind_key(st, keyent, pg_offset);
   3086 
   3087 	if (retval == 0) {
   3088 		keyent->kte_pgoff = pg_offset;
   3089 		keyent->kte_bound = 1;
   3090 	}
   3091 
   3092 	return (retval);
   3093 }
   3094 
   3095 static int
   3096 ioctl_agpgart_unbind(agpgart_softstate_t  *st, void  *arg, int flags)
   3097 {
   3098 	int key, retval = 0;
   3099 	agp_unbind_t unbindinfo;
   3100 	keytable_ent_t *keyent;
   3101 
   3102 	if (is_controlling_proc(st) < 0) {
   3103 		AGPDB_PRINT2((CE_WARN,
   3104 		    "ioctl_agpgart_bind: not a controlling process"));
   3105 		return (EPERM);
   3106 	}
   3107 
   3108 	if (ddi_copyin(arg, &unbindinfo, sizeof (unbindinfo), flags) != 0) {
   3109 		return (EFAULT);
   3110 	}
   3111 	key = unbindinfo.agpu_key;
   3112 	if ((key >= AGP_MAXKEYS) || key < 0) {
   3113 		AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_unbind: invalid key"));
   3114 		return (EINVAL);
   3115 	}
   3116 	keyent = &st->asoft_table[key];
   3117 	if (!keyent->kte_bound) {
   3118 		return (EINVAL);
   3119 	}
   3120 
   3121 	if ((retval = agp_unbind_key(st, keyent)) != 0)
   3122 		return (retval);
   3123 
   3124 	return (0);
   3125 }
   3126 
   3127 static int
   3128 ioctl_agpgart_flush_chipset(agpgart_softstate_t *st)
   3129 {
   3130 	ldi_handle_t	hdl;
   3131 	uint32_t devid;
   3132 	int rc = 0;
   3133 	devid = st->asoft_info.agpki_mdevid;
   3134 	hdl = st->asoft_devreg.agprd_targethdl;
   3135 	if (IS_INTEL_915(devid) ||
   3136 	    IS_INTEL_965(devid) ||
   3137 	    IS_INTEL_X33(devid) ||
   3138 	    IS_INTEL_G4X(devid)) {
   3139 		rc = ldi_ioctl(hdl, INTEL_CHIPSET_FLUSH, 0, FKIOCTL, kcred, 0);
   3140 	}
   3141 	return	(rc);
   3142 }
   3143 
   3144 static int
   3145 ioctl_agpgart_pages_bind(agpgart_softstate_t  *st, void  *arg, int flags)
   3146 {
   3147 	agp_bind_pages_t 	bind_info;
   3148 	uint32_t	pg_offset;
   3149 	int err = 0;
   3150 	ldi_handle_t hdl;
   3151 	uint32_t npages;
   3152 	igd_gtt_seg_t *gttseg;
   3153 	uint32_t i;
   3154 	int rval;
   3155 	if (ddi_copyin(arg, &bind_info,
   3156 	    sizeof (agp_bind_pages_t), flags) != 0) {
   3157 		return (EFAULT);
   3158 	}
   3159 
   3160 	gttseg = (igd_gtt_seg_t *)kmem_zalloc(sizeof (igd_gtt_seg_t),
   3161 	    KM_SLEEP);
   3162 
   3163 	pg_offset = bind_info.agpb_pgstart;
   3164 
   3165 	gttseg->igs_pgstart =  pg_offset;
   3166 	npages = (uint32_t)bind_info.agpb_pgcount;
   3167 	gttseg->igs_npage = npages;
   3168 
   3169 	gttseg->igs_type = AGP_NORMAL;
   3170 	gttseg->igs_phyaddr = (uint32_t *)kmem_zalloc
   3171 	    (sizeof (uint32_t) * gttseg->igs_npage, KM_SLEEP);
   3172 
   3173 	for (i = 0; i < npages; i++) {
   3174 		gttseg->igs_phyaddr[i] = bind_info.agpb_pages[i] <<
   3175 		    GTT_PAGE_SHIFT;
   3176 	}
   3177 
   3178 	hdl = st->asoft_devreg.agprd_masterhdl;
   3179 	if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)gttseg, FKIOCTL,
   3180 	    kcred, &rval)) {
   3181 		AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: start0x%x",
   3182 		    gttseg->igs_pgstart));
   3183 		AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: pages=0x%x",
   3184 		    gttseg->igs_npage));
   3185 		AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: type=0x%x",
   3186 		    gttseg->igs_type));
   3187 		err = -1;
   3188 	}
   3189 
   3190 	list_head_add_new(&st->mapped_list, gttseg);
   3191 	return (err);
   3192 }
   3193 
   3194 static int
   3195 ioctl_agpgart_pages_unbind(agpgart_softstate_t  *st, void  *arg, int flags)
   3196 {
   3197 	agp_unbind_pages_t unbind_info;
   3198 	int	rval;
   3199 	ldi_handle_t	hdl;
   3200 	igd_gtt_seg_t	*gttseg;
   3201 
   3202 	if (ddi_copyin(arg, &unbind_info, sizeof (unbind_info), flags) != 0) {
   3203 		return (EFAULT);
   3204 	}
   3205 
   3206 	struct list_head  *entry, *temp;
   3207 	list_head_for_each_safe(entry, temp, &st->mapped_list) {
   3208 		if (entry->gttseg->igs_pgstart == unbind_info.agpb_pgstart) {
   3209 			gttseg = entry->gttseg;
   3210 			/* not unbind if VT switch */
   3211 			if (unbind_info.agpb_type) {
   3212 				list_head_del(entry);
   3213 				kmem_free(entry, sizeof (*entry));
   3214 			}
   3215 			break;
   3216 		}
   3217 	}
   3218 	ASSERT(gttseg != NULL);
   3219 	gttseg->igs_pgstart =  unbind_info.agpb_pgstart;
   3220 	ASSERT(gttseg->igs_npage == unbind_info.agpb_pgcount);
   3221 
   3222 	hdl = st->asoft_devreg.agprd_masterhdl;
   3223 	if (ldi_ioctl(hdl, I8XX_REM_GTT, (intptr_t)gttseg, FKIOCTL,
   3224 	    kcred, &rval))
   3225 		return (-1);
   3226 
   3227 	if (unbind_info.agpb_type) {
   3228 		kmem_free(gttseg->igs_phyaddr, sizeof (uint32_t) *
   3229 		    gttseg->igs_npage);
   3230 		kmem_free(gttseg, sizeof (igd_gtt_seg_t));
   3231 	}
   3232 
   3233 	return (0);
   3234 }
   3235 
   3236 static int
   3237 ioctl_agpgart_pages_rebind(agpgart_softstate_t  *st)
   3238 {
   3239 	int	rval;
   3240 	ldi_handle_t	hdl;
   3241 	igd_gtt_seg_t	*gttseg;
   3242 	int err = 0;
   3243 
   3244 	hdl = st->asoft_devreg.agprd_masterhdl;
   3245 	struct list_head  *entry, *temp;
   3246 	list_head_for_each_safe(entry, temp, &st->mapped_list) {
   3247 		gttseg = entry->gttseg;
   3248 		list_head_del(entry);
   3249 		kmem_free(entry, sizeof (*entry));
   3250 		if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)gttseg, FKIOCTL,
   3251 		    kcred, &rval)) {
   3252 			AGPDB_PRINT2((CE_WARN, "agpgart_pages_rebind errori"));
   3253 			err = -1;
   3254 			break;
   3255 		}
   3256 		kmem_free(gttseg->igs_phyaddr, sizeof (uint32_t) *
   3257 		    gttseg->igs_npage);
   3258 		kmem_free(gttseg, sizeof (igd_gtt_seg_t));
   3259 
   3260 	}
   3261 	return (err);
   3262 
   3263 }
   3264 
   3265 /*ARGSUSED*/
   3266 static int
   3267 agpgart_ioctl(dev_t dev, int cmd, intptr_t intarg, int flags,
   3268     cred_t *credp, int *rvalp)
   3269 {
   3270 	int instance;
   3271 	int retval = 0;
   3272 	void *arg = (void*)intarg;
   3273 
   3274 	agpgart_softstate_t *softstate;
   3275 
   3276 	instance = AGP_DEV2INST(dev);
   3277 	softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
   3278 	if (softstate == NULL) {
   3279 		AGPDB_PRINT2((CE_WARN, "agpgart_ioctl: get soft state err"));
   3280 		return (ENXIO);
   3281 	}
   3282 
   3283 	mutex_enter(&softstate->asoft_instmutex);
   3284 
   3285 	switch (cmd) {
   3286 	case AGPIOC_INFO:
   3287 		retval = ioctl_agpgart_info(softstate, arg, flags);
   3288 		break;
   3289 	case AGPIOC_ACQUIRE:
   3290 		retval = ioctl_agpgart_acquire(softstate);
   3291 		break;
   3292 	case AGPIOC_RELEASE:
   3293 		retval = ioctl_agpgart_release(softstate);
   3294 		break;
   3295 	case AGPIOC_SETUP:
   3296 		retval = ioctl_agpgart_setup(softstate, arg, flags);
   3297 		break;
   3298 	case AGPIOC_ALLOCATE:
   3299 		retval = ioctl_agpgart_alloc(softstate, arg, flags);
   3300 		break;
   3301 	case AGPIOC_DEALLOCATE:
   3302 		retval = ioctl_agpgart_dealloc(softstate, intarg);
   3303 		break;
   3304 	case AGPIOC_BIND:
   3305 		retval = ioctl_agpgart_bind(softstate, arg, flags);
   3306 		break;
   3307 	case AGPIOC_UNBIND:
   3308 		retval = ioctl_agpgart_unbind(softstate, arg, flags);
   3309 		break;
   3310 	case AGPIOC_FLUSHCHIPSET:
   3311 		retval = ioctl_agpgart_flush_chipset(softstate);
   3312 		break;
   3313 	case AGPIOC_PAGES_BIND:
   3314 		retval = ioctl_agpgart_pages_bind(softstate, arg, flags);
   3315 		break;
   3316 	case AGPIOC_PAGES_UNBIND:
   3317 		retval = ioctl_agpgart_pages_unbind(softstate, arg, flags);
   3318 		break;
   3319 	case AGPIOC_PAGES_REBIND:
   3320 		retval = ioctl_agpgart_pages_rebind(softstate);
   3321 		break;
   3322 	default:
   3323 		AGPDB_PRINT2((CE_WARN, "agpgart_ioctl: wrong argument"));
   3324 		retval = ENXIO;
   3325 		break;
   3326 	}
   3327 
   3328 	mutex_exit(&softstate->asoft_instmutex);
   3329 	return (retval);
   3330 }
   3331 
   3332 static int
   3333 agpgart_segmap(dev_t dev, off_t off, struct as *asp,
   3334     caddr_t *addrp, off_t len, unsigned int prot,
   3335     unsigned int maxprot, unsigned int flags, cred_t *credp)
   3336 {
   3337 
   3338 	struct agpgart_softstate *softstate;
   3339 	int instance;
   3340 	int rc = 0;
   3341 
   3342 	instance = AGP_DEV2INST(dev);
   3343 	softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
   3344 	if (softstate == NULL) {
   3345 		AGPDB_PRINT2((CE_WARN, "agpgart_segmap: get soft state err"));
   3346 		return (ENXIO);
   3347 	}
   3348 	if (!AGP_ALIGNED(len))
   3349 		return (EINVAL);
   3350 
   3351 	mutex_enter(&softstate->asoft_instmutex);
   3352 
   3353 	rc = devmap_setup(dev, (offset_t)off, asp, addrp,
   3354 	    (size_t)len, prot, maxprot, flags, credp);
   3355 
   3356 	mutex_exit(&softstate->asoft_instmutex);
   3357 	return (rc);
   3358 }
   3359 
   3360 /*ARGSUSED*/
   3361 static int
   3362 agpgart_devmap(dev_t dev, devmap_cookie_t cookie, offset_t offset, size_t len,
   3363     size_t *mappedlen, uint_t model)
   3364 {
   3365 	struct agpgart_softstate *softstate;
   3366 	int instance, status;
   3367 	struct keytable_ent *mementry;
   3368 	offset_t local_offset;
   3369 
   3370 	instance = AGP_DEV2INST(dev);
   3371 	softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
   3372 	if (softstate == NULL) {
   3373 		AGPDB_PRINT2((CE_WARN, "agpgart_devmap: get soft state err"));
   3374 		return (ENXIO);
   3375 	}
   3376 
   3377 
   3378 	if (offset > MB2BYTES(softstate->asoft_info.agpki_apersize)) {
   3379 		AGPDB_PRINT2((CE_WARN, "agpgart_devmap: offset is too large"));
   3380 		return (EINVAL);
   3381 	}
   3382 
   3383 	/*
   3384 	 * Can not find any memory now, so fail.
   3385 	 */
   3386 
   3387 	mementry = agp_find_bound_keyent(softstate, AGP_BYTES2PAGES(offset));
   3388 
   3389 	if (mementry == NULL) {
   3390 		AGPDB_PRINT2((CE_WARN,
   3391 		    "agpgart_devmap: can not find the proper keyent"));
   3392 		return (EINVAL);
   3393 	}
   3394 
   3395 	local_offset = offset - AGP_PAGES2BYTES(mementry->kte_pgoff);
   3396 
   3397 	if (len > (AGP_PAGES2BYTES(mementry->kte_pages) - local_offset)) {
   3398 		len = AGP_PAGES2BYTES(mementry->kte_pages) - local_offset;
   3399 	}
   3400 
   3401 	switch (mementry->kte_type) {
   3402 	case AGP_NORMAL:
   3403 		if (PMEMP(mementry->kte_memhdl)->pmem_cookie) {
   3404 			status = devmap_pmem_setup(cookie,
   3405 			    softstate->asoft_dip,
   3406 			    &agp_devmap_cb,
   3407 			    PMEMP(mementry->kte_memhdl)->pmem_cookie,
   3408 			    local_offset,
   3409 			    len, PROT_ALL,
   3410 			    (DEVMAP_DEFAULTS|IOMEM_DATA_UC_WR_COMBINE),
   3411 			    &mem_dev_acc_attr);
   3412 		} else {
   3413 			AGPDB_PRINT2((CE_WARN,
   3414 			    "agpgart_devmap: not a valid memory type"));
   3415 			return (EINVAL);
   3416 
   3417 		}
   3418 
   3419 		break;
   3420 	default:
   3421 		AGPDB_PRINT2((CE_WARN,
   3422 		    "agpgart_devmap: not a valid memory type"));
   3423 		return (EINVAL);
   3424 	}
   3425 
   3426 
   3427 	if (status == 0) {
   3428 		*mappedlen = len;
   3429 	} else {
   3430 		*mappedlen = 0;
   3431 		AGPDB_PRINT2((CE_WARN,
   3432 		    "agpgart_devmap: devmap interface failed"));
   3433 		return (EINVAL);
   3434 	}
   3435 
   3436 	return (0);
   3437 }
   3438 
   3439 static struct cb_ops	agpgart_cb_ops = {
   3440 	agpgart_open,		/* open() */
   3441 	agpgart_close,		/* close() */
   3442 	nodev,			/* strategy() */
   3443 	nodev,			/* print routine */
   3444 	nodev,			/* no dump routine */
   3445 	nodev,			/* read() */
   3446 	nodev,			/* write() */
   3447 	agpgart_ioctl,		/* agpgart_ioctl */
   3448 	agpgart_devmap,		/* devmap routine */
   3449 	nodev,			/* no longer use mmap routine */
   3450 	agpgart_segmap,		/* system segmap routine */
   3451 	nochpoll,		/* no chpoll routine */
   3452 	ddi_prop_op,		/* system prop operations */
   3453 	0,			/* not a STREAMS driver */
   3454 	D_DEVMAP | D_MP,	/* safe for multi-thread/multi-processor */
   3455 	CB_REV,			/* cb_ops version? */
   3456 	nodev,			/* cb_aread() */
   3457 	nodev,			/* cb_awrite() */
   3458 };
   3459 
   3460 static struct dev_ops agpgart_ops = {
   3461 	DEVO_REV,		/* devo_rev */
   3462 	0,			/* devo_refcnt */
   3463 	agpgart_getinfo,	/* devo_getinfo */
   3464 	nulldev,		/* devo_identify */
   3465 	nulldev,		/* devo_probe */
   3466 	agpgart_attach,		/* devo_attach */
   3467 	agpgart_detach,		/* devo_detach */
   3468 	nodev,			/* devo_reset */
   3469 	&agpgart_cb_ops,	/* devo_cb_ops */
   3470 	(struct bus_ops *)0,	/* devo_bus_ops */
   3471 	NULL,			/* devo_power */
   3472 	ddi_quiesce_not_needed,	/* devo_quiesce */
   3473 };
   3474 
   3475 static	struct modldrv modldrv = {
   3476 	&mod_driverops,
   3477 	"AGP driver",
   3478 	&agpgart_ops,
   3479 };
   3480 
   3481 static struct modlinkage modlinkage = {
   3482 	MODREV_1,		/* MODREV_1 is indicated by manual */
   3483 	{&modldrv, NULL, NULL, NULL}
   3484 };
   3485 
   3486 static void *agpgart_glob_soft_handle;
   3487 
   3488 int
   3489 _init(void)
   3490 {
   3491 	int ret = DDI_SUCCESS;
   3492 
   3493 	ret = ddi_soft_state_init(&agpgart_glob_soft_handle,
   3494 	    sizeof (agpgart_softstate_t),
   3495 	    AGPGART_MAX_INSTANCES);
   3496 
   3497 	if (ret != 0) {
   3498 		AGPDB_PRINT2((CE_WARN,
   3499 		    "_init: soft state init error code=0x%x", ret));
   3500 		return (ret);
   3501 	}
   3502 
   3503 	if ((ret = mod_install(&modlinkage)) != 0) {
   3504 		AGPDB_PRINT2((CE_WARN,
   3505 		    "_init: mod install error code=0x%x", ret));
   3506 		ddi_soft_state_fini(&agpgart_glob_soft_handle);
   3507 		return (ret);
   3508 	}
   3509 
   3510 	return (DDI_SUCCESS);
   3511 }
   3512 
   3513 int
   3514 _info(struct modinfo *modinfop)
   3515 {
   3516 	return (mod_info(&modlinkage, modinfop));
   3517 }
   3518 
   3519 int
   3520 _fini(void)
   3521 {
   3522 	int ret;
   3523 
   3524 	if ((ret = mod_remove(&modlinkage)) == 0) {
   3525 		ddi_soft_state_fini(&agpgart_glob_soft_handle);
   3526 	}
   3527 
   3528 	return (ret);
   3529 }
   3530