xref: /titanic_44/usr/src/uts/intel/io/agpgart/agpgart.c (revision 9b79392525856301c6f8962f189c2a32242af618)
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@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