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