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