xref: /titanic_44/usr/src/uts/intel/io/agpgart/agptarget.c (revision 7fb8ff4b4ab2a12889658b03b56f34c849689221)
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 		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
364 		switch (memval & I8XX_GC_MODE_MASK) {
365 		case I8XX_GC_MODE1:
366 			kbytes = 1024; /* 1M preallocated memory */
367 			break;
368 		case I8XX_GC_MODE3:
369 			kbytes = 8 * 1024; /* 8M preallocated memory */
370 			break;
371 		default:
372 			kbytes = 0; /* an unexpected case */
373 		}
374 		break;
375 	default:
376 		kbytes = 0;
377 	}
378 
379 	TARGETDB_PRINT2((CE_NOTE,
380 	    "i8xx_biosmem_detect: %ldKB BIOS pre-allocated memory detected",
381 	    kbytes));
382 	return (kbytes);
383 }
384 
385 /*ARGSUSED*/
386 static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
387     void *arg, void **resultp)
388 {
389 	agp_target_softstate_t *st;
390 	int instance, rval = DDI_FAILURE;
391 	dev_t dev;
392 
393 	switch (cmd) {
394 	case DDI_INFO_DEVT2DEVINFO:
395 		dev = (dev_t)arg;
396 		instance = DEV2INST(dev);
397 		st = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
398 		if (st != NULL) {
399 			mutex_enter(&st->tsoft_lock);
400 			*resultp = st->tsoft_dip;
401 			mutex_exit(&st->tsoft_lock);
402 			rval = DDI_SUCCESS;
403 		} else
404 			*resultp = NULL;
405 
406 		break;
407 	case DDI_INFO_DEVT2INSTANCE:
408 		dev = (dev_t)arg;
409 		instance = DEV2INST(dev);
410 		*resultp = (void *)(uintptr_t)instance;
411 		rval = DDI_SUCCESS;
412 	default:
413 		break;
414 	}
415 
416 	return (rval);
417 }
418 
419 static int
420 agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
421 {
422 	agp_target_softstate_t *softstate;
423 	int instance;
424 	int status;
425 
426 	if (cmd != DDI_ATTACH)
427 		return (DDI_FAILURE);
428 
429 	instance = ddi_get_instance(dip);
430 
431 	if (ddi_soft_state_zalloc(agptarget_glob_soft_handle, instance) !=
432 	    DDI_SUCCESS)
433 		return (DDI_FAILURE);
434 
435 	softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
436 	mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL);
437 	softstate->tsoft_dip = dip;
438 	status = pci_config_setup(dip, &softstate->tsoft_pcihdl);
439 	if (status != DDI_SUCCESS) {
440 		ddi_soft_state_free(agptarget_glob_soft_handle, instance);
441 		return (DDI_FAILURE);
442 	}
443 
444 	softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl,
445 	    PCI_CONF_VENID);
446 	softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl);
447 	if (softstate->tsoft_acaptr == 0) {
448 		/* Make a correction for some Intel chipsets */
449 		if ((softstate->tsoft_devid & VENDOR_ID_MASK) ==
450 		    INTEL_VENDOR_ID)
451 			softstate->tsoft_acaptr = AGP_CAP_OFF_DEF;
452 		else
453 			return (DDI_FAILURE);
454 	}
455 
456 	status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR,
457 	    INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0);
458 
459 	if (status != DDI_SUCCESS) {
460 		pci_config_teardown(&softstate->tsoft_pcihdl);
461 		ddi_soft_state_free(agptarget_glob_soft_handle, instance);
462 		return (DDI_FAILURE);
463 	}
464 
465 	return (DDI_SUCCESS);
466 }
467 
468 /*ARGSUSED*/
469 static int
470 agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
471 {
472 	int instance;
473 	agp_target_softstate_t *softstate;
474 
475 	if (cmd != DDI_DETACH)
476 		return (DDI_FAILURE);
477 
478 	instance = ddi_get_instance(dip);
479 
480 	softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
481 
482 	ddi_remove_minor_node(dip, AGPTARGET_NAME);
483 	pci_config_teardown(&softstate->tsoft_pcihdl);
484 	mutex_destroy(&softstate->tsoft_lock);
485 	ddi_soft_state_free(agptarget_glob_soft_handle, instance);
486 	return (DDI_SUCCESS);
487 }
488 
489 /*ARGSUSED*/
490 static int
491 agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
492     cred_t *cred, int *rval)
493 {
494 	int instance = DEV2INST(dev);
495 	agp_target_softstate_t *st;
496 	static char kernel_only[] =
497 	    "amd64_gart_ioctl: is a kernel only ioctl";
498 
499 	if (!(mode & FKIOCTL)) {
500 		TARGETDB_PRINT2((CE_CONT, kernel_only));
501 		return (ENXIO);
502 	}
503 	st = GETSOFTC(instance);
504 
505 	if (st == NULL)
506 		return (ENXIO);
507 
508 	mutex_enter(&st->tsoft_lock);
509 
510 	switch (cmd) {
511 	case CHIP_DETECT:
512 	{
513 		int type;
514 		switch (st->tsoft_devid & VENDOR_ID_MASK) {
515 		case INTEL_VENDOR_ID:
516 			type = CHIP_IS_INTEL;
517 			break;
518 		case AMD_VENDOR_ID:
519 			type = CHIP_IS_AMD;
520 			break;
521 		default:
522 			type = 0;
523 		}
524 		if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) {
525 			mutex_exit(&st->tsoft_lock);
526 			return (EFAULT);
527 		}
528 
529 		break;
530 	}
531 	case I8XX_GET_PREALLOC_SIZE:
532 	{
533 		size_t prealloc_size;
534 
535 		if ((st->tsoft_devid & VENDOR_ID_MASK) !=
536 		    INTEL_VENDOR_ID) {
537 			mutex_exit(&st->tsoft_lock);
538 			return (EINVAL);
539 		}
540 
541 		prealloc_size = i8xx_biosmem_detect(st);
542 		if (ddi_copyout(&prealloc_size, (void *)data,
543 		    sizeof (size_t), mode)) {
544 			mutex_exit(&st->tsoft_lock);
545 			return (EFAULT);
546 		}
547 
548 		break;
549 	}
550 	case AGP_TARGET_GETINFO:
551 	{
552 		i_agp_info_t info;
553 		uint32_t value;
554 		off_t cap;
555 
556 		ASSERT(st->tsoft_acaptr);
557 
558 		cap = st->tsoft_acaptr;
559 		value = pci_config_get32(st->tsoft_pcihdl, cap);
560 		info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf);
561 		info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf);
562 		info.iagp_devid = st->tsoft_devid;
563 		info.iagp_mode = pci_config_get32(st->tsoft_pcihdl,
564 		    cap + AGP_CONF_STATUS);
565 		info.iagp_aperbase = agp_target_get_apbase(st);
566 		info.iagp_apersize = agp_target_get_apsize(st);
567 
568 		if (ddi_copyout(&info, (void *)data,
569 		    sizeof (i_agp_info_t), mode)) {
570 			mutex_exit(&st->tsoft_lock);
571 			return (EFAULT);
572 		}
573 		break;
574 
575 	}
576 	/*
577 	 * This ioctl is only for Intel AGP chipsets.
578 	 * It is not necessary for the AMD8151 AGP bridge, because
579 	 * this register in the AMD8151 does not control any hardware.
580 	 * It is only provided for compatibility with an Intel AGP bridge.
581 	 * Please refer to the <<AMD8151 data sheet>> page 24,
582 	 * AGP device GART pointer.
583 	 */
584 	case AGP_TARGET_SET_GATTADDR:
585 	{
586 		uint32_t gartaddr;
587 
588 		if (ddi_copyin((void *)data, &gartaddr,
589 		    sizeof (uint32_t), mode)) {
590 			mutex_exit(&st->tsoft_lock);
591 			return (EFAULT);
592 		}
593 
594 		agp_target_set_gartaddr(st, gartaddr);
595 		break;
596 	}
597 	case AGP_TARGET_SETCMD:
598 	{
599 		uint32_t command;
600 
601 		if (ddi_copyin((void *)data, &command,
602 		    sizeof (uint32_t), mode)) {
603 			mutex_exit(&st->tsoft_lock);
604 			return (EFAULT);
605 		}
606 
607 		ASSERT(st->tsoft_acaptr);
608 
609 		pci_config_put32(st->tsoft_pcihdl,
610 		    st->tsoft_acaptr + AGP_CONF_COMMAND,
611 		    command);
612 		break;
613 
614 	}
615 	case AGP_TARGET_FLUSH_GTLB:
616 	{
617 		uint16_t value;
618 
619 		ASSERT(st->tsoft_acaptr);
620 
621 		value = pci_config_get16(st->tsoft_pcihdl,
622 		    st->tsoft_acaptr + AGP_CONF_CONTROL);
623 		value &= ~AGPCTRL_GTLBEN;
624 		pci_config_put16(st->tsoft_pcihdl,
625 		    st->tsoft_acaptr + AGP_CONF_CONTROL, value);
626 		value |= AGPCTRL_GTLBEN;
627 		pci_config_put16(st->tsoft_pcihdl,
628 		    st->tsoft_acaptr + AGP_CONF_CONTROL, value);
629 
630 		break;
631 	}
632 	case AGP_TARGET_CONFIGURE:
633 	{
634 		uint8_t value;
635 
636 		ASSERT(st->tsoft_acaptr);
637 
638 		value = pci_config_get8(st->tsoft_pcihdl,
639 		    st->tsoft_acaptr + AGP_CONF_MISC);
640 		value |= AGP_MISC_APEN;
641 		pci_config_put8(st->tsoft_pcihdl,
642 		    st->tsoft_acaptr + AGP_CONF_MISC, value);
643 		break;
644 
645 	}
646 	case AGP_TARGET_UNCONFIG:
647 	{
648 		uint32_t value1;
649 		uint8_t value2;
650 
651 		ASSERT(st->tsoft_acaptr);
652 
653 		pci_config_put16(st->tsoft_pcihdl,
654 		    st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0);
655 
656 		value2 = pci_config_get8(st->tsoft_pcihdl,
657 		    st->tsoft_acaptr + AGP_CONF_MISC);
658 		value2 &= ~AGP_MISC_APEN;
659 		pci_config_put8(st->tsoft_pcihdl,
660 		    st->tsoft_acaptr + AGP_CONF_MISC, value2);
661 
662 		value1 = pci_config_get32(st->tsoft_pcihdl,
663 		    st->tsoft_acaptr + AGP_CONF_COMMAND);
664 		value1 &= ~AGPCMD_AGPEN;
665 		pci_config_put32(st->tsoft_pcihdl,
666 		    st->tsoft_acaptr + AGP_CONF_COMMAND,
667 		    value1);
668 
669 		pci_config_put32(st->tsoft_pcihdl,
670 		    st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0);
671 
672 		break;
673 	}
674 
675 	default:
676 		mutex_exit(&st->tsoft_lock);
677 		return (ENXIO);
678 	} /* end switch */
679 
680 	mutex_exit(&st->tsoft_lock);
681 
682 	return (0);
683 }
684 
685 /*ARGSUSED*/
686 static int
687 agp_target_open(dev_t *devp, int flag, int otyp, cred_t *cred)
688 {
689 	int instance = DEV2INST(*devp);
690 	agp_target_softstate_t *st;
691 
692 	if (!(flag & FKLYR))
693 		return (ENXIO);
694 
695 	st = GETSOFTC(instance);
696 
697 	if (st == NULL)
698 		return (ENXIO);
699 
700 	return (0);
701 }
702 
703 /*ARGSUSED*/
704 static int
705 agp_target_close(dev_t dev, int flag, int otyp, cred_t *cred)
706 {
707 	int instance = DEV2INST(dev);
708 	agp_target_softstate_t *st;
709 
710 	st = GETSOFTC(instance);
711 
712 	if (st == NULL)
713 		return (ENXIO);
714 
715 	return (0);
716 }
717 
718 static  struct  cb_ops  agp_target_cb_ops = {
719 	agp_target_open,		/* cb_open */
720 	agp_target_close,		/* cb_close */
721 	nodev,				/* cb_strategy */
722 	nodev,				/* cb_print */
723 	nodev,				/* cb_dump */
724 	nodev,				/* cb_read() */
725 	nodev,				/* cb_write() */
726 	agp_target_ioctl,		/* cb_ioctl */
727 	nodev,				/* cb_devmap */
728 	nodev,				/* cb_mmap */
729 	nodev,				/* cb_segmap */
730 	nochpoll,			/* cb_chpoll */
731 	ddi_prop_op,			/* cb_prop_op */
732 	0,				/* cb_stream */
733 	D_NEW | D_MP, 			/* cb_flag */
734 	CB_REV,				/* cb_ops version? */
735 	nodev,				/* cb_aread() */
736 	nodev,				/* cb_awrite() */
737 };
738 
739 /* device operations */
740 static struct dev_ops agp_target_ops = {
741 	DEVO_REV,		/* devo_rev */
742 	0,			/* devo_refcnt */
743 	agptarget_getinfo, 	/* devo_getinfo */
744 	nulldev,		/* devo_identify */
745 	nulldev,		/* devo_probe */
746 	agp_target_attach,	/* devo_attach */
747 	agp_target_detach,	/* devo_detach */
748 	nodev,			/* devo_reset */
749 	&agp_target_cb_ops,	/* devo_cb_ops */
750 	0,			/* devo_bus_ops */
751 	0,			/* devo_power */
752 };
753 
754 static  struct modldrv modldrv = {
755 	&mod_driverops,
756 	"AGP target driver v%I%",
757 	&agp_target_ops,
758 };
759 
760 static  struct modlinkage modlinkage = {
761 	MODREV_1,		/* MODREV_1 is indicated by manual */
762 	{&modldrv, NULL, NULL, NULL}
763 };
764 
765 int
766 _init(void)
767 {
768 	int ret;
769 
770 	ret = ddi_soft_state_init(&agptarget_glob_soft_handle,
771 	    sizeof (agp_target_softstate_t), 1);
772 
773 	if (ret)
774 		goto err1;
775 
776 	if ((ret = mod_install(&modlinkage)) != 0) {
777 		goto err2;
778 	}
779 
780 	return (DDI_SUCCESS);
781 err2:
782 	ddi_soft_state_fini(&agptarget_glob_soft_handle);
783 err1:
784 	return (ret);
785 }
786 
787 int
788 _info(struct  modinfo *modinfop)
789 {
790 	return (mod_info(&modlinkage, modinfop));
791 }
792 
793 int
794 _fini(void)
795 {
796 	int	ret;
797 
798 	if ((ret = mod_remove(&modlinkage)) == 0) {
799 		ddi_soft_state_fini(&agptarget_glob_soft_handle);
800 	}
801 	return (ret);
802 }
803