xref: /titanic_50/usr/src/uts/intel/io/agpgart/amd64_gart.c (revision 193974072f41a843678abf5f61979c748687e66b)
1ae115bc7Smrj /*
2613b2871SRichard Bean  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3ae115bc7Smrj  * Use is subject to license terms.
4ae115bc7Smrj  */
5ae115bc7Smrj 
6ae115bc7Smrj #include <sys/conf.h>
7ae115bc7Smrj #include <sys/ddi.h>
8ae115bc7Smrj #include <sys/sunddi.h>
9ae115bc7Smrj #include <sys/modctl.h>
10ae115bc7Smrj #include <sys/stat.h>
11ae115bc7Smrj #include <sys/sunldi.h>
12ae115bc7Smrj #include <sys/file.h>
13ae115bc7Smrj #include <sys/agpgart.h>
14ae115bc7Smrj #include <sys/agp/agpdefs.h>
15ae115bc7Smrj #include <sys/agp/agpamd64gart_io.h>
16ae115bc7Smrj 
17ae115bc7Smrj #define	MAX_GART_INSTS		8
18ae115bc7Smrj #define	GETSOFTC(instance)	((amd64_gart_softstate_t *)	\
19ae115bc7Smrj     ddi_get_soft_state(amd64_gart_glob_soft_handle, (instance)));
20ae115bc7Smrj #define	DEV2INST(dev)		(getminor(dev))
21ae115bc7Smrj #define	INST2NODENUM(inst)	(inst)
22ae115bc7Smrj 
23ae115bc7Smrj int amd64_debug_var = 0;
24ae115bc7Smrj #define	AMD64DB_PRINT1(fmt)	if (amd64_debug_var == 1) cmn_err fmt
25ae115bc7Smrj #define	AMD64DB_PRINT2(fmt)	if (amd64_debug_var >= 1) cmn_err fmt
26ae115bc7Smrj 
27ae115bc7Smrj typedef struct amd64_gart_softstate {
28ae115bc7Smrj 	dev_info_t		*gsoft_dip;
29ae115bc7Smrj 	ddi_acc_handle_t	gsoft_pcihdl;
30ae115bc7Smrj 	kmutex_t		gsoft_lock;
31ae115bc7Smrj }amd64_gart_softstate_t;
32ae115bc7Smrj 
33ae115bc7Smrj static void *amd64_gart_glob_soft_handle;
34ae115bc7Smrj 
35ae115bc7Smrj static uint64_t
amd64_get_aperbase(amd64_gart_softstate_t * sc)36ae115bc7Smrj amd64_get_aperbase(amd64_gart_softstate_t *sc)
37ae115bc7Smrj {
38ae115bc7Smrj 	uint32_t	value;
39ae115bc7Smrj 	uint64_t	aper_base;
40ae115bc7Smrj 
41ae115bc7Smrj 	/* amd64 aperture base support 40 bits and 32M aligned */
42ae115bc7Smrj 	value = pci_config_get32(sc->gsoft_pcihdl,
43ae115bc7Smrj 	    AMD64_APERTURE_BASE) & AMD64_APERBASE_MASK;
44ae115bc7Smrj 	aper_base = (uint64_t)value << AMD64_APERBASE_SHIFT;
45ae115bc7Smrj 	return (aper_base);
46ae115bc7Smrj }
47ae115bc7Smrj 
48ae115bc7Smrj static size_t
amd64_get_apersize(amd64_gart_softstate_t * sc)49ae115bc7Smrj amd64_get_apersize(amd64_gart_softstate_t *sc)
50ae115bc7Smrj {
51ae115bc7Smrj 	uint32_t	value;
52ae115bc7Smrj 	size_t		size;
53ae115bc7Smrj 
54ae115bc7Smrj 	value = pci_config_get32(sc->gsoft_pcihdl, AMD64_APERTURE_CONTROL);
55ae115bc7Smrj 
56ae115bc7Smrj 	value = (value & AMD64_APERSIZE_MASK) >> 1;
57ae115bc7Smrj 
58ae115bc7Smrj 	/* aper size = 2^value x 32 */
59ae115bc7Smrj 	switch (value) {
60ae115bc7Smrj 		case  0x0:
61ae115bc7Smrj 			size = 32;
62ae115bc7Smrj 			break;
63ae115bc7Smrj 		case  0x1:
64ae115bc7Smrj 			size = 64;
65ae115bc7Smrj 			break;
66ae115bc7Smrj 		case  0x2:
67ae115bc7Smrj 			size = 128;
68ae115bc7Smrj 			break;
69ae115bc7Smrj 		case  0x3:
70ae115bc7Smrj 			size = 256;
71ae115bc7Smrj 			break;
72ae115bc7Smrj 		case  0x4:
73ae115bc7Smrj 			size = 512;
74ae115bc7Smrj 			break;
75ae115bc7Smrj 		case  0x5:
76ae115bc7Smrj 			size = 1024;
77ae115bc7Smrj 			break;
78ae115bc7Smrj 		case  0x6:
79ae115bc7Smrj 			size = 2048;
80ae115bc7Smrj 			break;
81ae115bc7Smrj 		default:		/* reserved */
82ae115bc7Smrj 			size = 0;
83ae115bc7Smrj 	};
84ae115bc7Smrj 
85ae115bc7Smrj 	return (size);
86ae115bc7Smrj }
87ae115bc7Smrj 
88ae115bc7Smrj static void
amd64_invalidate_gtlb(amd64_gart_softstate_t * sc)89ae115bc7Smrj amd64_invalidate_gtlb(amd64_gart_softstate_t *sc)
90ae115bc7Smrj {
91ae115bc7Smrj 	uint32_t value;
92ae115bc7Smrj 
93ae115bc7Smrj 	value = pci_config_get32(sc->gsoft_pcihdl, AMD64_GART_CACHE_CTL);
94ae115bc7Smrj 	value |= AMD64_INVALID_CACHE;
95ae115bc7Smrj 
96ae115bc7Smrj 	pci_config_put32(sc->gsoft_pcihdl, AMD64_GART_CACHE_CTL, value);
97ae115bc7Smrj }
98ae115bc7Smrj 
99ae115bc7Smrj static void
amd64_enable_gart(amd64_gart_softstate_t * sc,int enable)100ae115bc7Smrj amd64_enable_gart(amd64_gart_softstate_t *sc, int enable)
101ae115bc7Smrj {
102ae115bc7Smrj 	uint32_t aper_ctl;
103ae115bc7Smrj 	uint32_t aper_base;
104ae115bc7Smrj 	uint32_t gart_ctl;
105ae115bc7Smrj 	uint32_t gart_base;
106ae115bc7Smrj 
107ae115bc7Smrj 	aper_ctl = pci_config_get32(sc->gsoft_pcihdl, AMD64_APERTURE_CONTROL);
108ae115bc7Smrj 	AMD64DB_PRINT1((CE_NOTE, "before: aper_ctl = %x", aper_ctl));
109ae115bc7Smrj 	aper_base = pci_config_get32(sc->gsoft_pcihdl, AMD64_APERTURE_BASE);
110ae115bc7Smrj 	gart_ctl = pci_config_get32(sc->gsoft_pcihdl, AMD64_GART_CACHE_CTL);
111ae115bc7Smrj 	gart_base = pci_config_get32(sc->gsoft_pcihdl, AMD64_GART_BASE);
112ae115bc7Smrj #ifdef lint
113ae115bc7Smrj 	aper_base = aper_base;
114ae115bc7Smrj 	gart_ctl = gart_ctl;
115ae115bc7Smrj 	gart_base = gart_base;
116ae115bc7Smrj #endif /* lint */
117ae115bc7Smrj 	AMD64DB_PRINT1((CE_NOTE, "before: aper_base = %x", aper_base));
118ae115bc7Smrj 	AMD64DB_PRINT1((CE_NOTE, "before: gart_ctl = %x", gart_ctl));
119ae115bc7Smrj 	AMD64DB_PRINT1((CE_NOTE, "before: gart_base = %x", gart_base));
120ae115bc7Smrj 	if (enable) {
121ae115bc7Smrj 		aper_ctl |= AMD64_GARTEN;
122ae115bc7Smrj 		aper_ctl &= ~(AMD64_DISGARTCPU | AMD64_DISGARTIO);
123ae115bc7Smrj 	} else
124ae115bc7Smrj 		aper_ctl &= (~AMD64_GARTEN);
125ae115bc7Smrj 
126ae115bc7Smrj 	pci_config_put32(sc->gsoft_pcihdl, AMD64_APERTURE_CONTROL, aper_ctl);
127ae115bc7Smrj }
128ae115bc7Smrj 
129ae115bc7Smrj /*ARGSUSED*/
130ae115bc7Smrj static int
amd64_gart_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)131ae115bc7Smrj amd64_gart_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
132ae115bc7Smrj     void *arg, void **resultp)
133ae115bc7Smrj {
134ae115bc7Smrj 	amd64_gart_softstate_t *st;
135ae115bc7Smrj 	int instance, rval = DDI_FAILURE;
136ae115bc7Smrj 	dev_t dev;
137ae115bc7Smrj 
138ae115bc7Smrj 	switch (cmd) {
139ae115bc7Smrj 	case DDI_INFO_DEVT2DEVINFO:
140ae115bc7Smrj 		dev = (dev_t)arg;
141ae115bc7Smrj 		instance = DEV2INST(dev);
142ae115bc7Smrj 		st = ddi_get_soft_state(amd64_gart_glob_soft_handle, instance);
143ae115bc7Smrj 		if (st != NULL) {
144ae115bc7Smrj 			mutex_enter(&st->gsoft_lock);
145ae115bc7Smrj 			*resultp = st->gsoft_dip;
146ae115bc7Smrj 			mutex_exit(&st->gsoft_lock);
147ae115bc7Smrj 			rval = DDI_SUCCESS;
148ae115bc7Smrj 		} else {
149ae115bc7Smrj 			*resultp = NULL;
150ae115bc7Smrj 		}
151ae115bc7Smrj 
152ae115bc7Smrj 		break;
153ae115bc7Smrj 	case DDI_INFO_DEVT2INSTANCE:
154ae115bc7Smrj 		dev = (dev_t)arg;
155ae115bc7Smrj 		instance = DEV2INST(dev);
156ae115bc7Smrj 		*resultp = (void *)(uintptr_t)instance;
157ae115bc7Smrj 		rval = DDI_SUCCESS;
158ae115bc7Smrj 		break;
159ae115bc7Smrj 	default:
160ae115bc7Smrj 		break;
161ae115bc7Smrj 	}
162ae115bc7Smrj 
163ae115bc7Smrj 	return (rval);
164ae115bc7Smrj }
165ae115bc7Smrj 
166ae115bc7Smrj static int
amd64_gart_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)167ae115bc7Smrj amd64_gart_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
168ae115bc7Smrj {
169ae115bc7Smrj 	int			instance;
170ae115bc7Smrj 	amd64_gart_softstate_t	*sc;
171ae115bc7Smrj 	int			status;
172ae115bc7Smrj 	char			buf[80];
173ae115bc7Smrj 
1742df1fe9cSrandyf 	switch (cmd) {
1752df1fe9cSrandyf 	default:
176ae115bc7Smrj 		return (DDI_FAILURE);
177ae115bc7Smrj 
1782df1fe9cSrandyf 	case DDI_RESUME:
1792df1fe9cSrandyf 		/* Nothing special is needed for resume. */
1802df1fe9cSrandyf 		return (DDI_SUCCESS);
1812df1fe9cSrandyf 
1822df1fe9cSrandyf 	case DDI_ATTACH:
1832df1fe9cSrandyf 		break;
1842df1fe9cSrandyf 	}
1852df1fe9cSrandyf 
186ae115bc7Smrj 	instance = ddi_get_instance(dip);
187ae115bc7Smrj 
188ae115bc7Smrj 	if (ddi_soft_state_zalloc(amd64_gart_glob_soft_handle, instance) !=
189ae115bc7Smrj 	    DDI_SUCCESS)
190ae115bc7Smrj 		return (DDI_FAILURE);
191ae115bc7Smrj 
192ae115bc7Smrj 	sc = ddi_get_soft_state(amd64_gart_glob_soft_handle, instance);
193ae115bc7Smrj 	mutex_init(&sc->gsoft_lock, NULL, MUTEX_DRIVER, NULL);
194ae115bc7Smrj 	sc->gsoft_dip = dip;
195ae115bc7Smrj 	status = pci_config_setup(dip, &sc->gsoft_pcihdl);
196ae115bc7Smrj 	if (status != DDI_SUCCESS) {
197ae115bc7Smrj 		ddi_soft_state_free(amd64_gart_glob_soft_handle, instance);
198ae115bc7Smrj 		return (DDI_FAILURE);
199ae115bc7Smrj 	}
200ae115bc7Smrj 	(void) sprintf(buf, "%s-%d", AMD64GART_NAME, instance);
201ae115bc7Smrj 	status = ddi_create_minor_node(dip, buf, S_IFCHR,
202ae115bc7Smrj 	    INST2NODENUM(instance), DDI_NT_AGP_CPUGART, 0);
203ae115bc7Smrj 	if (status != DDI_SUCCESS) {
204ae115bc7Smrj 		pci_config_teardown(&sc->gsoft_pcihdl);
205ae115bc7Smrj 		ddi_soft_state_free(amd64_gart_glob_soft_handle, instance);
206ae115bc7Smrj 		return (DDI_FAILURE);
207ae115bc7Smrj 	}
208ae115bc7Smrj 	return (DDI_SUCCESS);
209ae115bc7Smrj }
210ae115bc7Smrj 
211ae115bc7Smrj /*ARGSUSED*/
212ae115bc7Smrj static int
amd64_gart_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)213ae115bc7Smrj amd64_gart_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
214ae115bc7Smrj {
215ae115bc7Smrj 	int			instance;
216ae115bc7Smrj 	amd64_gart_softstate_t	*sc;
217ae115bc7Smrj 	char			buf[80];
218ae115bc7Smrj 
2192df1fe9cSrandyf 	switch (cmd) {
2202df1fe9cSrandyf 	default:
221ae115bc7Smrj 		return (DDI_FAILURE);
222ae115bc7Smrj 
2232df1fe9cSrandyf 	case DDI_SUSPEND:
2242df1fe9cSrandyf 		/* Nothing special is needed for suspend */
2252df1fe9cSrandyf 		return (DDI_SUCCESS);
2262df1fe9cSrandyf 
2272df1fe9cSrandyf 	case DDI_DETACH:
2282df1fe9cSrandyf 		break;
2292df1fe9cSrandyf 	}
2302df1fe9cSrandyf 
231ae115bc7Smrj 	instance = ddi_get_instance(dip);
232ae115bc7Smrj 	sc = ddi_get_soft_state(amd64_gart_glob_soft_handle, instance);
233ae115bc7Smrj 
234ae115bc7Smrj 	(void) sprintf(buf, "%s-%d", AMD64GART_NAME, instance);
235ae115bc7Smrj 	ddi_remove_minor_node(dip, buf);
236ae115bc7Smrj 	pci_config_teardown(&sc->gsoft_pcihdl);
237ae115bc7Smrj 	mutex_destroy(&sc->gsoft_lock);
238ae115bc7Smrj 	ddi_soft_state_free(amd64_gart_glob_soft_handle, instance);
239ae115bc7Smrj 
240ae115bc7Smrj 	return (DDI_SUCCESS);
241ae115bc7Smrj }
242ae115bc7Smrj 
243ae115bc7Smrj /*ARGSUSED*/
244ae115bc7Smrj static int
amd64_gart_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * cred,int * rval)245ae115bc7Smrj amd64_gart_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
246ae115bc7Smrj     cred_t *cred, int *rval)
247ae115bc7Smrj {
248ae115bc7Smrj 	int instance;
249ae115bc7Smrj 	amd64_gart_softstate_t *sc;
250ae115bc7Smrj 	static char kernel_only[] =
251ae115bc7Smrj 	    "amd64_gart_ioctl: is a kernel only ioctl";
252ae115bc7Smrj 
253ae115bc7Smrj 	if (!(mode & FKIOCTL)) {
254ae115bc7Smrj 		AMD64DB_PRINT2((CE_CONT, kernel_only));
255ae115bc7Smrj 		return (ENXIO);
256ae115bc7Smrj 	}
257ae115bc7Smrj 	instance = DEV2INST(dev);
258ae115bc7Smrj 	sc = GETSOFTC(instance);
259ae115bc7Smrj 
260ae115bc7Smrj 	if (sc == NULL)
261ae115bc7Smrj 		return (ENXIO);
262ae115bc7Smrj 	mutex_enter(&sc->gsoft_lock);
263ae115bc7Smrj 
264ae115bc7Smrj 	switch (cmd) {
265ae115bc7Smrj 	case AMD64_GET_INFO:
266ae115bc7Smrj 	{
267ae115bc7Smrj 		amdgart_info_t info;
268ae115bc7Smrj 
269ae115bc7Smrj 		info.cgart_aperbase = amd64_get_aperbase(sc);
270ae115bc7Smrj 		info.cgart_apersize = amd64_get_apersize(sc);
271ae115bc7Smrj 
272ae115bc7Smrj 		if (ddi_copyout(&info, (void *)data,
273ae115bc7Smrj 		    sizeof (amdgart_info_t), mode)) {
274ae115bc7Smrj 			mutex_exit(&sc->gsoft_lock);
275ae115bc7Smrj 			return (EFAULT);
276ae115bc7Smrj 		}
277ae115bc7Smrj 		break;
278ae115bc7Smrj 	}
279ae115bc7Smrj 	case AMD64_SET_GART_ADDR:
280ae115bc7Smrj 	{
281ae115bc7Smrj 		uint32_t addr;
282ae115bc7Smrj 
283ae115bc7Smrj 		if (ddi_copyin((void *)data, &addr, sizeof (uint32_t), mode)) {
284ae115bc7Smrj 			mutex_exit(&sc->gsoft_lock);
285ae115bc7Smrj 			return (EFAULT);
286ae115bc7Smrj 		}
287ae115bc7Smrj 
288ae115bc7Smrj 		pci_config_put32(sc->gsoft_pcihdl, AMD64_GART_BASE, addr);
289ae115bc7Smrj 		amd64_enable_gart(sc, 1);
290ae115bc7Smrj 
291ae115bc7Smrj 		break;
292ae115bc7Smrj 	}
293ae115bc7Smrj 	case AMD64_FLUSH_GTLB:
294ae115bc7Smrj 	{
295ae115bc7Smrj 		amd64_invalidate_gtlb(sc);
296ae115bc7Smrj 
297ae115bc7Smrj 		break;
298ae115bc7Smrj 	}
299ae115bc7Smrj 	case AMD64_CONFIGURE:
300ae115bc7Smrj 	{
301ae115bc7Smrj 		/* reserved */
302ae115bc7Smrj 		break;
303ae115bc7Smrj 	}
304ae115bc7Smrj 	case AMD64_UNCONFIG:
305ae115bc7Smrj 	{
306ae115bc7Smrj 		amd64_enable_gart(sc, 0);
307ae115bc7Smrj 		pci_config_put32(sc->gsoft_pcihdl, AMD64_GART_BASE, 0x00000000);
308ae115bc7Smrj 
309ae115bc7Smrj 		break;
310ae115bc7Smrj 	}
311ae115bc7Smrj 	default:
312ae115bc7Smrj 		mutex_exit(&sc->gsoft_lock);
313ae115bc7Smrj 		return (ENXIO);
314ae115bc7Smrj 
315ae115bc7Smrj 	}
316ae115bc7Smrj 
317ae115bc7Smrj 	mutex_exit(&sc->gsoft_lock);
318ae115bc7Smrj 
319ae115bc7Smrj 	return (0);
320ae115bc7Smrj }
321ae115bc7Smrj 
322ae115bc7Smrj /*ARGSUSED*/
323ae115bc7Smrj static int
amd64_gart_open(dev_t * dev,int flag,int otyp,cred_t * cred)324ae115bc7Smrj amd64_gart_open(dev_t *dev, int flag, int otyp, cred_t *cred)
325ae115bc7Smrj {
326ae115bc7Smrj 	int			instance;
327ae115bc7Smrj 	amd64_gart_softstate_t	*sc;
328ae115bc7Smrj 
329ae115bc7Smrj 	if (!(flag & FKLYR))
330ae115bc7Smrj 		return (ENXIO);
331ae115bc7Smrj 
332ae115bc7Smrj 	instance = DEV2INST(*dev);
333ae115bc7Smrj 	sc = GETSOFTC(instance);
334ae115bc7Smrj 
335ae115bc7Smrj 	if (sc == NULL)
336ae115bc7Smrj 		return (ENXIO);
337ae115bc7Smrj 
338ae115bc7Smrj 	return (0);
339ae115bc7Smrj }
340ae115bc7Smrj 
341ae115bc7Smrj /*ARGSUSED*/
342ae115bc7Smrj static int
amd64_gart_close(dev_t dev,int flag,int otyp,cred_t * cred)343ae115bc7Smrj amd64_gart_close(dev_t dev, int flag, int otyp, cred_t *cred)
344ae115bc7Smrj {
345ae115bc7Smrj 	int			instance;
346ae115bc7Smrj 	amd64_gart_softstate_t	*sc;
347ae115bc7Smrj 
348ae115bc7Smrj 	instance = DEV2INST(dev);
349ae115bc7Smrj 	sc = GETSOFTC(instance);
350ae115bc7Smrj 
351ae115bc7Smrj 	if (sc == NULL)
352ae115bc7Smrj 		return (ENXIO);
353ae115bc7Smrj 
354ae115bc7Smrj 	return (0);
355ae115bc7Smrj }
356ae115bc7Smrj 
357ae115bc7Smrj static  struct  cb_ops  amd64_gart_cb_ops = {
358ae115bc7Smrj 	amd64_gart_open,	/* cb_open() */
359ae115bc7Smrj 	amd64_gart_close,	/* cb_close() */
360ae115bc7Smrj 	nodev,			/* cb_strategy() */
361ae115bc7Smrj 	nodev,			/* cb_print */
362ae115bc7Smrj 	nodev,			/* cb_dump */
363ae115bc7Smrj 	nodev,			/* cb_read() */
364ae115bc7Smrj 	nodev,			/* cb_write() */
365ae115bc7Smrj 	amd64_gart_ioctl,	/* cb_ioctl */
366ae115bc7Smrj 	nodev,			/* cb_devmap */
367ae115bc7Smrj 	nodev,			/* cb_mmap */
368ae115bc7Smrj 	nodev,			/* cb_segmap */
369ae115bc7Smrj 	nochpoll,		/* cb_chpoll */
370ae115bc7Smrj 	ddi_prop_op,		/* cb_prop_op */
371ae115bc7Smrj 	0,			/* cb_stream */
372ae115bc7Smrj 	D_NEW | D_MP,		/* cb_flag */
373ae115bc7Smrj 	CB_REV,			/* cb_ops version? */
374ae115bc7Smrj 	nodev,			/* cb_aread() */
375ae115bc7Smrj 	nodev,			/* cb_awrite() */
376ae115bc7Smrj };
377ae115bc7Smrj 
378ae115bc7Smrj /* device operations */
379ae115bc7Smrj static struct dev_ops amd64_gart_ops = {
380ae115bc7Smrj 	DEVO_REV,		/* devo_rev */
381ae115bc7Smrj 	0,			/* devo_refcnt */
382ae115bc7Smrj 	amd64_gart_getinfo,	/* devo_getinfo */
383ae115bc7Smrj 	nulldev,		/* devo_identify */
384ae115bc7Smrj 	nulldev,		/* devo_probe */
385ae115bc7Smrj 	amd64_gart_attach,	/* devo_attach */
386ae115bc7Smrj 	amd64_gart_detach,	/* devo_detach */
387ae115bc7Smrj 	nodev,			/* devo_reset */
388ae115bc7Smrj 	&amd64_gart_cb_ops,	/* devo_cb_ops */
389ae115bc7Smrj 	0,			/* devo_bus_ops */
390ae115bc7Smrj 	0,			/* devo_power */
391*19397407SSherry Moore 	ddi_quiesce_not_needed,	/* devo_quiesce */
392ae115bc7Smrj };
393ae115bc7Smrj 
394ae115bc7Smrj static  struct modldrv modldrv = {
395ae115bc7Smrj 	&mod_driverops,
396613b2871SRichard Bean 	"AGP AMD gart driver",
397ae115bc7Smrj 	&amd64_gart_ops,
398ae115bc7Smrj };
399ae115bc7Smrj 
400ae115bc7Smrj static  struct modlinkage modlinkage = {
401ae115bc7Smrj 	MODREV_1,		/* MODREV_1 is indicated by manual */
402ae115bc7Smrj 	&modldrv,
403ae115bc7Smrj 	NULL
404ae115bc7Smrj };
405ae115bc7Smrj 
406ae115bc7Smrj 
407ae115bc7Smrj int
_init(void)408ae115bc7Smrj _init(void)
409ae115bc7Smrj {
410ae115bc7Smrj 	int ret = DDI_SUCCESS;
411ae115bc7Smrj 
412ae115bc7Smrj 	ret = ddi_soft_state_init(&amd64_gart_glob_soft_handle,
413ae115bc7Smrj 	    sizeof (amd64_gart_softstate_t),
414ae115bc7Smrj 	    MAX_GART_INSTS);
415ae115bc7Smrj 
416ae115bc7Smrj 	if (ret)
417ae115bc7Smrj 		return (ret);
418ae115bc7Smrj 	if ((ret = mod_install(&modlinkage)) != 0) {
419ae115bc7Smrj 		ddi_soft_state_fini(&amd64_gart_glob_soft_handle);
420ae115bc7Smrj 		return (ret);
421ae115bc7Smrj 	}
422ae115bc7Smrj 	return (DDI_SUCCESS);
423ae115bc7Smrj }
424ae115bc7Smrj 
425ae115bc7Smrj int
_info(struct modinfo * modinfop)426ae115bc7Smrj _info(struct  modinfo *modinfop)
427ae115bc7Smrj {
428ae115bc7Smrj 	return (mod_info(&modlinkage, modinfop));
429ae115bc7Smrj }
430ae115bc7Smrj 
431ae115bc7Smrj int
_fini(void)432ae115bc7Smrj _fini(void)
433ae115bc7Smrj {
434ae115bc7Smrj 	int ret;
435ae115bc7Smrj 	if ((ret = mod_remove(&modlinkage)) == 0) {
436ae115bc7Smrj 		ddi_soft_state_fini(&amd64_gart_glob_soft_handle);
437ae115bc7Smrj 	}
438ae115bc7Smrj 	return (ret);
439ae115bc7Smrj }
440