xref: /titanic_50/usr/src/uts/intel/io/agpgart/agptarget.c (revision 29e83d4b25fd82feb8e0e0fbe89f7e2a8438533d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/systm.h>
30 #include <sys/conf.h>
31 #include <sys/modctl.h>
32 #include <sys/file.h>
33 #include <sys/stat.h>
34 #include <sys/ddi.h>
35 #include <sys/sunddi.h>
36 #include <sys/modctl.h>
37 #include <sys/sunldi.h>
38 #include <sys/pci.h>
39 #include <sys/agpgart.h>
40 #include <sys/agp/agpdefs.h>
41 #include <sys/agp/agptarget_io.h>
42 
43 int agptarget_debug_var = 0;
44 #define	TARGETDB_PRINT2(fmt)	if (agptarget_debug_var >= 1) cmn_err fmt
45 #define	INST2NODENUM(inst)	(inst)
46 #define	DEV2INST(dev)		(getminor(dev))
47 
48 typedef struct agp_target_softstate {
49 	dev_info_t		*tsoft_dip;
50 	ddi_acc_handle_t	tsoft_pcihdl;
51 	uint32_t		tsoft_devid;
52 	/* The offset of the ACAPID register */
53 	off_t			tsoft_acaptr;
54 	kmutex_t		tsoft_lock;
55 }agp_target_softstate_t;
56 
57 static void *agptarget_glob_soft_handle;
58 
59 #define	GETSOFTC(instance)	((agp_target_softstate_t *)	\
60     ddi_get_soft_state(agptarget_glob_soft_handle, instance));
61 
62 /*
63  * The AMD8151 bridge is the only supported 64 bit hardware
64  */
65 static int
66 is_64bit_aper(agp_target_softstate_t *softstate)
67 {
68 	return (softstate->tsoft_devid == AMD_BR_8151);
69 }
70 
71 /*
72  * agp_target_cap_find()
73  *
74  * Description:
75  * 	This function searches the linked capability list to find the offset
76  * 	of the AGP capability register. When it was not found, return 0.
77  * 	This works for standard AGP chipsets, but not for some Intel chipsets,
78  * 	like the I830M/I830MP/I852PM/I852GME/I855GME. It will return 0 for
79  * 	these chipsets even if AGP is supported. So the offset of acapid
80  * 	should be set manually in thoses cases.
81  *
82  * Arguments:
83  * 	pci_handle		ddi acc handle of pci config
84  *
85  * Returns:
86  * 	0			No capability pointer register found
87  * 	nexcap			The AGP capability pointer register offset
88  */
89 static off_t
90 agp_target_cap_find(ddi_acc_handle_t pci_handle)
91 {
92 	off_t		nextcap = 0;
93 	uint32_t	ncapid = 0;
94 	uint8_t		value = 0;
95 
96 	/* Check if this device supports the capability pointer */
97 	value = (uint8_t)(pci_config_get16(pci_handle, PCI_CONF_STAT)
98 	    & PCI_CONF_CAP_MASK);
99 
100 	if (!value)
101 		return (0);
102 	/* Get the offset of the first capability pointer from CAPPTR */
103 	nextcap = (off_t)(pci_config_get8(pci_handle, AGP_CONF_CAPPTR));
104 
105 	/* Check the AGP capability from the first capability pointer */
106 	while (nextcap) {
107 		ncapid = pci_config_get32(pci_handle, nextcap);
108 		/*
109 		 * AGP3.0 rev1.0 127  the capid was assigned by the PCI SIG,
110 		 * 845 data sheet page 69
111 		 */
112 		if ((ncapid & PCI_CONF_CAPID_MASK) ==
113 		    AGP_CAP_ID) /* The AGP cap was found */
114 			break;
115 
116 		nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8);
117 	}
118 
119 	return (nextcap);
120 
121 }
122 
123 /*
124  * agp_target_get_aperbase()
125  *
126  * Description:
127  * 	This function gets the AGP aperture base address from the AGP target
128  *	register, the AGP aperture base register was programmed by the BIOS.
129  *
130  * Arguments:
131  * 	softstate		driver soft state pointer
132  *
133  * Returns:
134  * 	aper_base 		AGP aperture base address
135  *
136  * Notes:
137  * 	If a 64bit bridge device is available, the AGP aperture base address
138  * 	can be 64 bit.
139  */
140 static uint64_t
141 agp_target_get_apbase(agp_target_softstate_t *softstate)
142 {
143 	uint64_t aper_base;
144 
145 	if (!is_64bit_aper(softstate)) {
146 		aper_base = pci_config_get32(softstate->tsoft_pcihdl,
147 		    AGP_CONF_APERBASE) & AGP_32_APERBASE_MASK;
148 	} else {
149 		aper_base = pci_config_get64(softstate->tsoft_pcihdl,
150 		    AGP_CONF_APERBASE);
151 		/* 32-bit or 64-bit aperbase base pointer */
152 		if ((aper_base & AGP_APER_TYPE_MASK) == 0)
153 			aper_base &= AGP_32_APERBASE_MASK;
154 		else
155 			aper_base &= AGP_64_APERBASE_MASK;
156 	}
157 	return (aper_base);
158 }
159 
160 /*
161  * agp_target_get_apsize()
162  *
163  * Description:
164  * 	This function gets the AGP aperture size by reading the AGP aperture
165  * 	size register.
166  * Arguments:
167  * 	softstate		driver soft state pointer
168  *
169  * Return:
170  * 	size		The AGP aperture size in megabytes
171  * 	0		an unexpected error
172  */
173 static size_t
174 agp_target_get_apsize(agp_target_softstate_t *softstate)
175 {
176 	off_t cap;
177 	uint16_t value;
178 	size_t size, regsize;
179 
180 	ASSERT(softstate->tsoft_acaptr);
181 	cap = softstate->tsoft_acaptr;
182 
183 	if ((softstate->tsoft_devid & VENDOR_ID_MASK) == INTEL_VENDOR_ID) {
184 		/* extend this value to 16 bit for later tests */
185 		value = (uint16_t)pci_config_get8(softstate->tsoft_pcihdl,
186 		    cap + AGP_CONF_APERSIZE) | AGP_APER_SIZE_MASK;
187 	} else {
188 		value = pci_config_get16(softstate->tsoft_pcihdl,
189 		    cap + AGP_CONF_APERSIZE);
190 	}
191 
192 	if (value & AGP_APER_128M_MASK) {
193 		switch (value & AGP_APER_128M_MASK) {
194 			case AGP_APER_4M:
195 				size = 4; /* 4M */
196 				break;
197 			case AGP_APER_8M:
198 				size = 8; /* 8M */
199 				break;
200 			case AGP_APER_16M:
201 				size = 16; /* 16M */
202 				break;
203 			case AGP_APER_32M:
204 				size = 32; /* 32M */
205 				break;
206 			case AGP_APER_64M:
207 				size = 64; /* 64M */
208 				break;
209 			case AGP_APER_128M:
210 				size = 128; /* 128M */
211 				break;
212 			default:
213 				size = 0; /* not true */
214 		}
215 	} else {
216 		switch (value & AGP_APER_4G_MASK) {
217 			case AGP_APER_256M:
218 				size = 256; /* 256 M */
219 				break;
220 			case AGP_APER_512M:
221 				size = 512; /* 512 M */
222 				break;
223 			case AGP_APER_1024M:
224 				size = 1024; /* 1024 M */
225 				break;
226 			case AGP_APER_2048M:
227 				size = 2048; /* 2048 M */
228 				break;
229 			case AGP_APER_4G:
230 				size = 4096; /* 4096 M */
231 				break;
232 			default:
233 				size = 0; /* not true */
234 		}
235 	}
236 	/*
237 	 * In some cases, there is no APSIZE register, so the size value
238 	 * of 256M could be wrong. Check the value by reading the size of
239 	 * the first register which was set in the PCI configuration space.
240 	 */
241 	if (size == 256) {
242 		if (ddi_dev_regsize(softstate->tsoft_dip,
243 		    AGP_TARGET_BAR1, (off_t *)&regsize) == DDI_FAILURE)
244 			return (0);
245 
246 		if (MB2BYTES(size) != regsize) {
247 			TARGETDB_PRINT2((CE_WARN,
248 			    "APSIZE 256M doesn't match regsize %lx",
249 			    regsize));
250 			TARGETDB_PRINT2((CE_WARN, "Use regsize instead"));
251 			size = BYTES2MB(regsize);
252 		}
253 	}
254 
255 	return (size);
256 }
257 
258 static void
259 agp_target_set_gartaddr(agp_target_softstate_t *softstate, uint32_t gartaddr)
260 {
261 	ASSERT(softstate->tsoft_acaptr);
262 
263 	/* Disable the GTLB for Intel chipsets */
264 	pci_config_put16(softstate->tsoft_pcihdl,
265 	    softstate->tsoft_acaptr + AGP_CONF_CONTROL, 0x0000);
266 
267 	pci_config_put32(softstate->tsoft_pcihdl,
268 	    softstate->tsoft_acaptr + AGP_CONF_ATTBASE,
269 	    gartaddr & AGP_ATTBASE_MASK);
270 }
271 
272 static size_t
273 i8xx_biosmem_detect(agp_target_softstate_t *softstate)
274 {
275 	uint8_t memval;
276 	size_t kbytes;
277 
278 	switch (softstate->tsoft_devid) {
279 	case INTEL_BR_810:
280 	case INTEL_BR_810DC:
281 	case INTEL_BR_810E:
282 		memval = pci_config_get8(softstate->tsoft_pcihdl,
283 		    I810_CONF_SMRAM);
284 		switch (memval & I810_GMS_MASK) {
285 		case 0x80:
286 			kbytes = 512; /* 512K preallocated memory */
287 			break;
288 		case 0xc0:
289 			kbytes = 1024; /* 1024K preallocated memory */
290 			break;
291 		default:
292 			kbytes = 0; /* an unexpected case */
293 		}
294 		break;
295 	case INTEL_BR_830M:
296 	case INTEL_BR_845:
297 		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
298 		switch (memval & I8XX_GC_MODE_MASK) {
299 		case I8XX_GC_MODE2:
300 			kbytes = 512; /* 512K preallocated memory */
301 			break;
302 		case I8XX_GC_MODE3:
303 			kbytes = 1024; /* 1M preallocated memory */
304 			break;
305 		case I8XX_GC_MODE4:
306 			kbytes = 8 * 1024; /* 8M preallocated memory */
307 			break;
308 		default:
309 			kbytes = 0; /* an unexpected case */
310 		}
311 		break;
312 	case INTEL_BR_855GM:
313 		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
314 		switch (memval & I8XX_GC_MODE_MASK) {
315 		case I8XX_GC_MODE1:
316 			kbytes = 1024; /* 1M preallocated memory */
317 			break;
318 		case I8XX_GC_MODE2:
319 			kbytes = 4 * 1024; /* 4M preallocated memory */
320 			break;
321 		case I8XX_GC_MODE3:
322 			kbytes = 8 * 1024; /* 8M preallocated memory */
323 			break;
324 		case I8XX_GC_MODE4:
325 			kbytes = 16 * 1024; /* 16M preallocated memory */
326 			break;
327 		case I8XX_GC_MODE5:
328 			kbytes = 32 * 1024; /* 32M preallocated memory */
329 			break;
330 		default:
331 			kbytes = 0; /* an unexpected case */
332 		}
333 		break;
334 	case INTEL_BR_865:
335 	case INTEL_BR_915GM:
336 		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
337 		switch (memval & I8XX_GC_MODE_MASK) {
338 		case I8XX_GC_MODE1:
339 			kbytes = 1024; /* 1M preallocated memory */
340 			break;
341 		case I8XX_GC_MODE3:
342 			kbytes = 8 * 1024; /* 8M preallocated memory */
343 			break;
344 		/*
345 		 * There is no option for 16M in 915GM datasheet,
346 		 * but some BIOS add this option for 16M support.
347 		 */
348 		case I8XX_GC_MODE4:
349 			kbytes = 16 * 1024; /* 16M preallocated memory */
350 			break;
351 		default:
352 			kbytes = 0; /* an unexpected case */
353 		}
354 		break;
355 	case INTEL_BR_915:
356 	case INTEL_BR_945:
357 	case INTEL_BR_945GM:
358 	case INTEL_BR_946GZ:
359 	case INTEL_BR_965G1:
360 	case INTEL_BR_965G2:
361 	case INTEL_BR_965Q:
362 	case INTEL_BR_965GM:
363 	case INTEL_BR_965GME:
364 		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
365 		switch (memval & I8XX_GC_MODE_MASK) {
366 		case I8XX_GC_MODE1:
367 			kbytes = 1024; /* 1M preallocated memory */
368 			break;
369 		case I8XX_GC_MODE3:
370 			kbytes = 8 * 1024; /* 8M preallocated memory */
371 			break;
372 		default:
373 			kbytes = 0; /* an unexpected case */
374 		}
375 		break;
376 	default:
377 		kbytes = 0;
378 	}
379 
380 	TARGETDB_PRINT2((CE_NOTE,
381 	    "i8xx_biosmem_detect: %ldKB BIOS pre-allocated memory detected",
382 	    kbytes));
383 	return (kbytes);
384 }
385 
386 /*ARGSUSED*/
387 static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
388     void *arg, void **resultp)
389 {
390 	agp_target_softstate_t *st;
391 	int instance, rval = DDI_FAILURE;
392 	dev_t dev;
393 
394 	switch (cmd) {
395 	case DDI_INFO_DEVT2DEVINFO:
396 		dev = (dev_t)arg;
397 		instance = DEV2INST(dev);
398 		st = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
399 		if (st != NULL) {
400 			mutex_enter(&st->tsoft_lock);
401 			*resultp = st->tsoft_dip;
402 			mutex_exit(&st->tsoft_lock);
403 			rval = DDI_SUCCESS;
404 		} else
405 			*resultp = NULL;
406 
407 		break;
408 	case DDI_INFO_DEVT2INSTANCE:
409 		dev = (dev_t)arg;
410 		instance = DEV2INST(dev);
411 		*resultp = (void *)(uintptr_t)instance;
412 		rval = DDI_SUCCESS;
413 	default:
414 		break;
415 	}
416 
417 	return (rval);
418 }
419 
420 static int
421 agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
422 {
423 	agp_target_softstate_t *softstate;
424 	int instance;
425 	int status;
426 
427 	if (cmd != DDI_ATTACH)
428 		return (DDI_FAILURE);
429 
430 	instance = ddi_get_instance(dip);
431 
432 	if (ddi_soft_state_zalloc(agptarget_glob_soft_handle, instance) !=
433 	    DDI_SUCCESS)
434 		return (DDI_FAILURE);
435 
436 	softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
437 	mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL);
438 	softstate->tsoft_dip = dip;
439 	status = pci_config_setup(dip, &softstate->tsoft_pcihdl);
440 	if (status != DDI_SUCCESS) {
441 		ddi_soft_state_free(agptarget_glob_soft_handle, instance);
442 		return (DDI_FAILURE);
443 	}
444 
445 	softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl,
446 	    PCI_CONF_VENID);
447 	softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl);
448 	if (softstate->tsoft_acaptr == 0) {
449 		/* Make a correction for some Intel chipsets */
450 		if ((softstate->tsoft_devid & VENDOR_ID_MASK) ==
451 		    INTEL_VENDOR_ID)
452 			softstate->tsoft_acaptr = AGP_CAP_OFF_DEF;
453 		else
454 			return (DDI_FAILURE);
455 	}
456 
457 	status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR,
458 	    INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0);
459 
460 	if (status != DDI_SUCCESS) {
461 		pci_config_teardown(&softstate->tsoft_pcihdl);
462 		ddi_soft_state_free(agptarget_glob_soft_handle, instance);
463 		return (DDI_FAILURE);
464 	}
465 
466 	return (DDI_SUCCESS);
467 }
468 
469 /*ARGSUSED*/
470 static int
471 agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
472 {
473 	int instance;
474 	agp_target_softstate_t *softstate;
475 
476 	if (cmd != DDI_DETACH)
477 		return (DDI_FAILURE);
478 
479 	instance = ddi_get_instance(dip);
480 
481 	softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
482 
483 	ddi_remove_minor_node(dip, AGPTARGET_NAME);
484 	pci_config_teardown(&softstate->tsoft_pcihdl);
485 	mutex_destroy(&softstate->tsoft_lock);
486 	ddi_soft_state_free(agptarget_glob_soft_handle, instance);
487 	return (DDI_SUCCESS);
488 }
489 
490 /*ARGSUSED*/
491 static int
492 agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
493     cred_t *cred, int *rval)
494 {
495 	int instance = DEV2INST(dev);
496 	agp_target_softstate_t *st;
497 	static char kernel_only[] =
498 	    "amd64_gart_ioctl: is a kernel only ioctl";
499 
500 	if (!(mode & FKIOCTL)) {
501 		TARGETDB_PRINT2((CE_CONT, kernel_only));
502 		return (ENXIO);
503 	}
504 	st = GETSOFTC(instance);
505 
506 	if (st == NULL)
507 		return (ENXIO);
508 
509 	mutex_enter(&st->tsoft_lock);
510 
511 	switch (cmd) {
512 	case CHIP_DETECT:
513 	{
514 		int type;
515 		switch (st->tsoft_devid & VENDOR_ID_MASK) {
516 		case INTEL_VENDOR_ID:
517 			type = CHIP_IS_INTEL;
518 			break;
519 		case AMD_VENDOR_ID:
520 			type = CHIP_IS_AMD;
521 			break;
522 		default:
523 			type = 0;
524 		}
525 		if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) {
526 			mutex_exit(&st->tsoft_lock);
527 			return (EFAULT);
528 		}
529 
530 		break;
531 	}
532 	case I8XX_GET_PREALLOC_SIZE:
533 	{
534 		size_t prealloc_size;
535 
536 		if ((st->tsoft_devid & VENDOR_ID_MASK) !=
537 		    INTEL_VENDOR_ID) {
538 			mutex_exit(&st->tsoft_lock);
539 			return (EINVAL);
540 		}
541 
542 		prealloc_size = i8xx_biosmem_detect(st);
543 		if (ddi_copyout(&prealloc_size, (void *)data,
544 		    sizeof (size_t), mode)) {
545 			mutex_exit(&st->tsoft_lock);
546 			return (EFAULT);
547 		}
548 
549 		break;
550 	}
551 	case AGP_TARGET_GETINFO:
552 	{
553 		i_agp_info_t info;
554 		uint32_t value;
555 		off_t cap;
556 
557 		ASSERT(st->tsoft_acaptr);
558 
559 		cap = st->tsoft_acaptr;
560 		value = pci_config_get32(st->tsoft_pcihdl, cap);
561 		info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf);
562 		info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf);
563 		info.iagp_devid = st->tsoft_devid;
564 		info.iagp_mode = pci_config_get32(st->tsoft_pcihdl,
565 		    cap + AGP_CONF_STATUS);
566 		info.iagp_aperbase = agp_target_get_apbase(st);
567 		info.iagp_apersize = agp_target_get_apsize(st);
568 
569 		if (ddi_copyout(&info, (void *)data,
570 		    sizeof (i_agp_info_t), mode)) {
571 			mutex_exit(&st->tsoft_lock);
572 			return (EFAULT);
573 		}
574 		break;
575 
576 	}
577 	/*
578 	 * This ioctl is only for Intel AGP chipsets.
579 	 * It is not necessary for the AMD8151 AGP bridge, because
580 	 * this register in the AMD8151 does not control any hardware.
581 	 * It is only provided for compatibility with an Intel AGP bridge.
582 	 * Please refer to the <<AMD8151 data sheet>> page 24,
583 	 * AGP device GART pointer.
584 	 */
585 	case AGP_TARGET_SET_GATTADDR:
586 	{
587 		uint32_t gartaddr;
588 
589 		if (ddi_copyin((void *)data, &gartaddr,
590 		    sizeof (uint32_t), mode)) {
591 			mutex_exit(&st->tsoft_lock);
592 			return (EFAULT);
593 		}
594 
595 		agp_target_set_gartaddr(st, gartaddr);
596 		break;
597 	}
598 	case AGP_TARGET_SETCMD:
599 	{
600 		uint32_t command;
601 
602 		if (ddi_copyin((void *)data, &command,
603 		    sizeof (uint32_t), mode)) {
604 			mutex_exit(&st->tsoft_lock);
605 			return (EFAULT);
606 		}
607 
608 		ASSERT(st->tsoft_acaptr);
609 
610 		pci_config_put32(st->tsoft_pcihdl,
611 		    st->tsoft_acaptr + AGP_CONF_COMMAND,
612 		    command);
613 		break;
614 
615 	}
616 	case AGP_TARGET_FLUSH_GTLB:
617 	{
618 		uint16_t value;
619 
620 		ASSERT(st->tsoft_acaptr);
621 
622 		value = pci_config_get16(st->tsoft_pcihdl,
623 		    st->tsoft_acaptr + AGP_CONF_CONTROL);
624 		value &= ~AGPCTRL_GTLBEN;
625 		pci_config_put16(st->tsoft_pcihdl,
626 		    st->tsoft_acaptr + AGP_CONF_CONTROL, value);
627 		value |= AGPCTRL_GTLBEN;
628 		pci_config_put16(st->tsoft_pcihdl,
629 		    st->tsoft_acaptr + AGP_CONF_CONTROL, value);
630 
631 		break;
632 	}
633 	case AGP_TARGET_CONFIGURE:
634 	{
635 		uint8_t value;
636 
637 		ASSERT(st->tsoft_acaptr);
638 
639 		value = pci_config_get8(st->tsoft_pcihdl,
640 		    st->tsoft_acaptr + AGP_CONF_MISC);
641 		value |= AGP_MISC_APEN;
642 		pci_config_put8(st->tsoft_pcihdl,
643 		    st->tsoft_acaptr + AGP_CONF_MISC, value);
644 		break;
645 
646 	}
647 	case AGP_TARGET_UNCONFIG:
648 	{
649 		uint32_t value1;
650 		uint8_t value2;
651 
652 		ASSERT(st->tsoft_acaptr);
653 
654 		pci_config_put16(st->tsoft_pcihdl,
655 		    st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0);
656 
657 		value2 = pci_config_get8(st->tsoft_pcihdl,
658 		    st->tsoft_acaptr + AGP_CONF_MISC);
659 		value2 &= ~AGP_MISC_APEN;
660 		pci_config_put8(st->tsoft_pcihdl,
661 		    st->tsoft_acaptr + AGP_CONF_MISC, value2);
662 
663 		value1 = pci_config_get32(st->tsoft_pcihdl,
664 		    st->tsoft_acaptr + AGP_CONF_COMMAND);
665 		value1 &= ~AGPCMD_AGPEN;
666 		pci_config_put32(st->tsoft_pcihdl,
667 		    st->tsoft_acaptr + AGP_CONF_COMMAND,
668 		    value1);
669 
670 		pci_config_put32(st->tsoft_pcihdl,
671 		    st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0);
672 
673 		break;
674 	}
675 
676 	default:
677 		mutex_exit(&st->tsoft_lock);
678 		return (ENXIO);
679 	} /* end switch */
680 
681 	mutex_exit(&st->tsoft_lock);
682 
683 	return (0);
684 }
685 
686 /*ARGSUSED*/
687 static int
688 agp_target_open(dev_t *devp, int flag, int otyp, cred_t *cred)
689 {
690 	int instance = DEV2INST(*devp);
691 	agp_target_softstate_t *st;
692 
693 	if (!(flag & FKLYR))
694 		return (ENXIO);
695 
696 	st = GETSOFTC(instance);
697 
698 	if (st == NULL)
699 		return (ENXIO);
700 
701 	return (0);
702 }
703 
704 /*ARGSUSED*/
705 static int
706 agp_target_close(dev_t dev, int flag, int otyp, cred_t *cred)
707 {
708 	int instance = DEV2INST(dev);
709 	agp_target_softstate_t *st;
710 
711 	st = GETSOFTC(instance);
712 
713 	if (st == NULL)
714 		return (ENXIO);
715 
716 	return (0);
717 }
718 
719 static  struct  cb_ops  agp_target_cb_ops = {
720 	agp_target_open,		/* cb_open */
721 	agp_target_close,		/* cb_close */
722 	nodev,				/* cb_strategy */
723 	nodev,				/* cb_print */
724 	nodev,				/* cb_dump */
725 	nodev,				/* cb_read() */
726 	nodev,				/* cb_write() */
727 	agp_target_ioctl,		/* cb_ioctl */
728 	nodev,				/* cb_devmap */
729 	nodev,				/* cb_mmap */
730 	nodev,				/* cb_segmap */
731 	nochpoll,			/* cb_chpoll */
732 	ddi_prop_op,			/* cb_prop_op */
733 	0,				/* cb_stream */
734 	D_NEW | D_MP, 			/* cb_flag */
735 	CB_REV,				/* cb_ops version? */
736 	nodev,				/* cb_aread() */
737 	nodev,				/* cb_awrite() */
738 };
739 
740 /* device operations */
741 static struct dev_ops agp_target_ops = {
742 	DEVO_REV,		/* devo_rev */
743 	0,			/* devo_refcnt */
744 	agptarget_getinfo, 	/* devo_getinfo */
745 	nulldev,		/* devo_identify */
746 	nulldev,		/* devo_probe */
747 	agp_target_attach,	/* devo_attach */
748 	agp_target_detach,	/* devo_detach */
749 	nodev,			/* devo_reset */
750 	&agp_target_cb_ops,	/* devo_cb_ops */
751 	0,			/* devo_bus_ops */
752 	0,			/* devo_power */
753 };
754 
755 static  struct modldrv modldrv = {
756 	&mod_driverops,
757 	"AGP target driver v%I%",
758 	&agp_target_ops,
759 };
760 
761 static  struct modlinkage modlinkage = {
762 	MODREV_1,		/* MODREV_1 is indicated by manual */
763 	{&modldrv, NULL, NULL, NULL}
764 };
765 
766 int
767 _init(void)
768 {
769 	int ret;
770 
771 	ret = ddi_soft_state_init(&agptarget_glob_soft_handle,
772 	    sizeof (agp_target_softstate_t), 1);
773 
774 	if (ret)
775 		goto err1;
776 
777 	if ((ret = mod_install(&modlinkage)) != 0) {
778 		goto err2;
779 	}
780 
781 	return (DDI_SUCCESS);
782 err2:
783 	ddi_soft_state_fini(&agptarget_glob_soft_handle);
784 err1:
785 	return (ret);
786 }
787 
788 int
789 _info(struct  modinfo *modinfop)
790 {
791 	return (mod_info(&modlinkage, modinfop));
792 }
793 
794 int
795 _fini(void)
796 {
797 	int	ret;
798 
799 	if ((ret = mod_remove(&modlinkage)) == 0) {
800 		ddi_soft_state_fini(&agptarget_glob_soft_handle);
801 	}
802 	return (ret);
803 }
804