xref: /titanic_50/usr/src/uts/common/io/drm/drm_ioctl.c (revision d0538f66491267879b7418b21ad78e3dcc2dcc83)
160405de4Skz151634 /*
260405de4Skz151634  * drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
360405de4Skz151634  * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
460405de4Skz151634  */
560405de4Skz151634 /*
660405de4Skz151634  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
760405de4Skz151634  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
860405de4Skz151634  * All Rights Reserved.
960405de4Skz151634  *
1060405de4Skz151634  * Permission is hereby granted, free of charge, to any person obtaining a
1160405de4Skz151634  * copy of this software and associated documentation files (the "Software"),
1260405de4Skz151634  * to deal in the Software without restriction, including without limitation
1360405de4Skz151634  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1460405de4Skz151634  * and/or sell copies of the Software, and to permit persons to whom the
1560405de4Skz151634  * Software is furnished to do so, subject to the following conditions:
1660405de4Skz151634  *
1760405de4Skz151634  * The above copyright notice and this permission notice (including the next
1860405de4Skz151634  * paragraph) shall be included in all copies or substantial portions of the
1960405de4Skz151634  * Software.
2060405de4Skz151634  *
2160405de4Skz151634  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2260405de4Skz151634  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2360405de4Skz151634  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2460405de4Skz151634  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2560405de4Skz151634  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2660405de4Skz151634  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2760405de4Skz151634  * OTHER DEALINGS IN THE SOFTWARE.
2860405de4Skz151634  *
2960405de4Skz151634  * Authors:
3060405de4Skz151634  *    Rickard E. (Rik) Faith <faith@valinux.com>
3160405de4Skz151634  *    Gareth Hughes <gareth@valinux.com>
3260405de4Skz151634  *
3360405de4Skz151634  */
3460405de4Skz151634 
35e92e3a86Szw161486 /*
36*d0538f66Scg149915  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37e92e3a86Szw161486  * Use is subject to license terms.
38e92e3a86Szw161486  */
39e92e3a86Szw161486 
4060405de4Skz151634 #pragma ident	"%Z%%M%	%I%	%E% SMI"
4160405de4Skz151634 
4260405de4Skz151634 #include "drmP.h"
43*d0538f66Scg149915 #include "drm_io32.h"
4460405de4Skz151634 
4560405de4Skz151634 /*
4660405de4Skz151634  * Beginning in revision 1.1 of the DRM interface, getunique will return
4760405de4Skz151634  * a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
4860405de4Skz151634  * before setunique has been called.  The format for the bus-specific part of
4960405de4Skz151634  * the unique is not defined for any other bus.
5060405de4Skz151634  */
5160405de4Skz151634 /*ARGSUSED*/
5260405de4Skz151634 int
drm_getunique(DRM_IOCTL_ARGS)5360405de4Skz151634 drm_getunique(DRM_IOCTL_ARGS)
5460405de4Skz151634 {
5560405de4Skz151634 	DRM_DEVICE;
5660405de4Skz151634 	drm_unique_t	 u1;
5760405de4Skz151634 
58*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
5960405de4Skz151634 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
60*d0538f66Scg149915 		drm_unique_32_t u32;
6160405de4Skz151634 
62*d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&u32, (void *)data, sizeof (u32));
6360405de4Skz151634 		u1.unique_len = u32.unique_len;
6460405de4Skz151634 		u1.unique = (char __user *)(uintptr_t)u32.unique;
6560405de4Skz151634 	} else
66*d0538f66Scg149915 #endif
67*d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&u1, (void *)data, sizeof (u1));
6860405de4Skz151634 
6960405de4Skz151634 	if (u1.unique_len >= dev->unique_len) {
7060405de4Skz151634 		if (dev->unique_len == 0) {
7160405de4Skz151634 			DRM_ERROR("drm_getunique: dev->unique_len = 0");
72*d0538f66Scg149915 			return (EFAULT);
7360405de4Skz151634 		}
7460405de4Skz151634 		if (DRM_COPY_TO_USER(u1.unique, dev->unique, dev->unique_len))
75*d0538f66Scg149915 			return (EFAULT);
7660405de4Skz151634 	}
7760405de4Skz151634 	u1.unique_len = dev->unique_len;
7860405de4Skz151634 
79*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
8060405de4Skz151634 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
81*d0538f66Scg149915 		drm_unique_32_t u32;
8260405de4Skz151634 
83*d0538f66Scg149915 		u32.unique_len = (uint32_t)u1.unique_len;
8460405de4Skz151634 		u32.unique = (caddr32_t)(uintptr_t)u1.unique;
85*d0538f66Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &u32, sizeof (u32));
8660405de4Skz151634 	} else
87*d0538f66Scg149915 #endif
88*d0538f66Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &u1, sizeof (u1));
8960405de4Skz151634 
9060405de4Skz151634 	return (0);
9160405de4Skz151634 }
9260405de4Skz151634 
9360405de4Skz151634 /*
9460405de4Skz151634  * Deprecated in DRM version 1.1, and will return EBUSY when setversion has
9560405de4Skz151634  * requested version 1.1 or greater.
9660405de4Skz151634  */
9760405de4Skz151634 /*ARGSUSED*/
9860405de4Skz151634 int
drm_setunique(DRM_IOCTL_ARGS)9960405de4Skz151634 drm_setunique(DRM_IOCTL_ARGS)
10060405de4Skz151634 {
101*d0538f66Scg149915 	return (EINVAL);
10260405de4Skz151634 }
10360405de4Skz151634 
10460405de4Skz151634 
10560405de4Skz151634 static int
drm_set_busid(drm_device_t * dev)10660405de4Skz151634 drm_set_busid(drm_device_t *dev)
10760405de4Skz151634 {
10860405de4Skz151634 	DRM_LOCK();
10960405de4Skz151634 
11060405de4Skz151634 	if (dev->unique != NULL) {
11160405de4Skz151634 		DRM_UNLOCK();
112*d0538f66Scg149915 		return (EBUSY);
11360405de4Skz151634 	}
11460405de4Skz151634 
11560405de4Skz151634 	dev->unique_len = 20;
11660405de4Skz151634 	dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
11760405de4Skz151634 	if (dev->unique == NULL) {
11860405de4Skz151634 		DRM_UNLOCK();
119*d0538f66Scg149915 		return (ENOMEM);
12060405de4Skz151634 	}
12160405de4Skz151634 
12260405de4Skz151634 	(void) snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
12360405de4Skz151634 	    dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
12460405de4Skz151634 
12560405de4Skz151634 	DRM_UNLOCK();
12660405de4Skz151634 
12760405de4Skz151634 	return (0);
12860405de4Skz151634 }
12960405de4Skz151634 
13060405de4Skz151634 /*ARGSUSED*/
13160405de4Skz151634 int
drm_getmap(DRM_IOCTL_ARGS)13260405de4Skz151634 drm_getmap(DRM_IOCTL_ARGS)
13360405de4Skz151634 {
13460405de4Skz151634 	DRM_DEVICE;
13560405de4Skz151634 	drm_map_t	map;
13660405de4Skz151634 	drm_local_map_t    *mapinlist;
13760405de4Skz151634 	int		idx;
13860405de4Skz151634 	int		i = 0;
13960405de4Skz151634 
140*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
14160405de4Skz151634 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
142*d0538f66Scg149915 		drm_map_32_t map32;
14360405de4Skz151634 
144*d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&map32, (void *)data, sizeof (map32));
14560405de4Skz151634 		map.offset = map32.offset;
14660405de4Skz151634 		map.size = map32.size;
14760405de4Skz151634 		map.type = map32.type;
14860405de4Skz151634 		map.flags = map32.flags;
14960405de4Skz151634 		map.handle = map32.handle;
15060405de4Skz151634 		map.mtrr = map32.mtrr;
15160405de4Skz151634 	} else
152*d0538f66Scg149915 #endif
153*d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&map, (void *)data, sizeof (map));
15460405de4Skz151634 
155*d0538f66Scg149915 	idx = (int)map.offset;
15660405de4Skz151634 
15760405de4Skz151634 	DRM_LOCK();
15860405de4Skz151634 	if (idx < 0) {
15960405de4Skz151634 		DRM_UNLOCK();
160*d0538f66Scg149915 		return (EINVAL);
16160405de4Skz151634 	}
16260405de4Skz151634 
16360405de4Skz151634 	TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
16460405de4Skz151634 		if (i == idx) {
165*d0538f66Scg149915 			map.offset = mapinlist->offset;
16660405de4Skz151634 			map.size   = mapinlist->size;
16760405de4Skz151634 			map.type   = mapinlist->type;
16860405de4Skz151634 			map.flags  = mapinlist->flags;
16960405de4Skz151634 			map.handle = (unsigned long long)(uintptr_t)
17060405de4Skz151634 			    mapinlist->handle;
17160405de4Skz151634 			map.mtrr   = mapinlist->mtrr;
17260405de4Skz151634 			break;
17360405de4Skz151634 		}
17460405de4Skz151634 		i++;
17560405de4Skz151634 	}
17660405de4Skz151634 
17760405de4Skz151634 	DRM_UNLOCK();
17860405de4Skz151634 
17960405de4Skz151634 	if (mapinlist == NULL)
180*d0538f66Scg149915 		return (EINVAL);
18160405de4Skz151634 
182*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
18360405de4Skz151634 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
184*d0538f66Scg149915 		drm_map_32_t map32;
18560405de4Skz151634 
18660405de4Skz151634 		map32.offset = map.offset;
187*d0538f66Scg149915 		map32.size = (uint32_t)map.size;
18860405de4Skz151634 		map32.type = map.type;
18960405de4Skz151634 		map32.flags = map.flags;
190*d0538f66Scg149915 		map32.handle = (uintptr_t)map.handle;
19160405de4Skz151634 		map32.mtrr = map.mtrr;
192*d0538f66Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &map32, sizeof (map32));
19360405de4Skz151634 	} else
194*d0538f66Scg149915 #endif
195*d0538f66Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &map, sizeof (map));
19660405de4Skz151634 
19760405de4Skz151634 	return (0);
19860405de4Skz151634 }
19960405de4Skz151634 
20060405de4Skz151634 /*ARGSUSED*/
20160405de4Skz151634 int
drm_getclient(DRM_IOCTL_ARGS)20260405de4Skz151634 drm_getclient(DRM_IOCTL_ARGS)
20360405de4Skz151634 {
20460405de4Skz151634 	DRM_DEVICE;
20560405de4Skz151634 	drm_client_t	client;
20660405de4Skz151634 	drm_file_t	*pt;
20760405de4Skz151634 	int		idx;
20860405de4Skz151634 	int		i = 0;
20960405de4Skz151634 
210*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
21160405de4Skz151634 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
212*d0538f66Scg149915 		drm_client_32_t client32;
21360405de4Skz151634 
214*d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&client32, (void *)data,
215*d0538f66Scg149915 		    sizeof (client32));
21660405de4Skz151634 		client.idx = client32.idx;
21760405de4Skz151634 		client.auth = client32.auth;
21860405de4Skz151634 		client.pid = client32.pid;
21960405de4Skz151634 		client.uid = client32.uid;
22060405de4Skz151634 		client.magic = client32.magic;
22160405de4Skz151634 		client.iocs = client32.iocs;
22260405de4Skz151634 	} else
223*d0538f66Scg149915 #endif
224*d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&client, (void *)data,
225*d0538f66Scg149915 		    sizeof (client));
22660405de4Skz151634 
22760405de4Skz151634 	idx = client.idx;
22860405de4Skz151634 	DRM_LOCK();
22960405de4Skz151634 	TAILQ_FOREACH(pt, &dev->files, link) {
23060405de4Skz151634 		if (i == idx) {
23160405de4Skz151634 			client.auth  = pt->authenticated;
23260405de4Skz151634 			client.pid   = pt->pid;
23360405de4Skz151634 			client.uid   = pt->uid;
23460405de4Skz151634 			client.magic = pt->magic;
23560405de4Skz151634 			client.iocs  = pt->ioctl_count;
23660405de4Skz151634 			DRM_UNLOCK();
23760405de4Skz151634 
238*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
23960405de4Skz151634 			if (ddi_model_convert_from(mode & FMODELS) ==
24060405de4Skz151634 			    DDI_MODEL_ILP32) {
241*d0538f66Scg149915 				drm_client_32_t client32;
24260405de4Skz151634 
24360405de4Skz151634 				client32.idx = client.idx;
24460405de4Skz151634 				client32.auth = client.auth;
245*d0538f66Scg149915 				client32.pid = (uint32_t)client.pid;
246*d0538f66Scg149915 				client32.uid = (uint32_t)client.uid;
247*d0538f66Scg149915 				client32.magic = (uint32_t)client.magic;
248*d0538f66Scg149915 				client32.iocs = (uint32_t)client.iocs;
24960405de4Skz151634 
250*d0538f66Scg149915 				DRM_COPYTO_WITH_RETURN((void *)data, &client32,
251*d0538f66Scg149915 				    sizeof (client32));
25260405de4Skz151634 			} else
253*d0538f66Scg149915 #endif
254*d0538f66Scg149915 				DRM_COPYTO_WITH_RETURN((void *)data,
255*d0538f66Scg149915 				    &client, sizeof (client));
25660405de4Skz151634 
25760405de4Skz151634 			return (0);
25860405de4Skz151634 		}
25960405de4Skz151634 		i++;
26060405de4Skz151634 	}
26160405de4Skz151634 	DRM_UNLOCK();
262*d0538f66Scg149915 	return (EINVAL);
26360405de4Skz151634 }
26460405de4Skz151634 
26560405de4Skz151634 /*ARGSUSED*/
26660405de4Skz151634 int
drm_getstats(DRM_IOCTL_ARGS)26760405de4Skz151634 drm_getstats(DRM_IOCTL_ARGS)
26860405de4Skz151634 {
26960405de4Skz151634 	DRM_DEVICE;
27060405de4Skz151634 	drm_stats_t	stats;
27160405de4Skz151634 	int		i;
27260405de4Skz151634 
27360405de4Skz151634 	bzero(&stats, sizeof (stats));
27460405de4Skz151634 
27560405de4Skz151634 	DRM_LOCK();
27660405de4Skz151634 
27760405de4Skz151634 	for (i = 0; i < dev->counters; i++) {
27860405de4Skz151634 		if (dev->types[i] == _DRM_STAT_LOCK) {
27960405de4Skz151634 			stats.data[i].value
28060405de4Skz151634 			    = (dev->lock.hw_lock
28160405de4Skz151634 			    ? dev->lock.hw_lock->lock : 0);
28260405de4Skz151634 		} else
28360405de4Skz151634 			stats.data[i].value = atomic_read(&dev->counts[i]);
28460405de4Skz151634 		stats.data[i].type  = dev->types[i];
28560405de4Skz151634 	}
28660405de4Skz151634 
28760405de4Skz151634 	stats.count = dev->counters;
28860405de4Skz151634 
28960405de4Skz151634 	DRM_UNLOCK();
29060405de4Skz151634 
291*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
29260405de4Skz151634 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
293*d0538f66Scg149915 		drm_stats_32_t stats32;
294*d0538f66Scg149915 		stats32.count = (uint32_t)stats.count;
29560405de4Skz151634 		for (i = 0; i < 15; i++) {
29660405de4Skz151634 			stats32.data[i].value = stats.data[i].value;
29760405de4Skz151634 			stats32.data[i].type = stats.data[i].type;
29860405de4Skz151634 		}
299*d0538f66Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &stats32,
300*d0538f66Scg149915 		    sizeof (stats32));
30160405de4Skz151634 	} else
302*d0538f66Scg149915 #endif
303*d0538f66Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &stats, sizeof (stats));
30460405de4Skz151634 
30560405de4Skz151634 	return (0);
30660405de4Skz151634 }
30760405de4Skz151634 
30860405de4Skz151634 #define	DRM_IF_MAJOR	1
309*d0538f66Scg149915 #define	DRM_IF_MINOR	2
31060405de4Skz151634 
31160405de4Skz151634 /*ARGSUSED*/
31260405de4Skz151634 int
drm_setversion(DRM_IOCTL_ARGS)31360405de4Skz151634 drm_setversion(DRM_IOCTL_ARGS)
31460405de4Skz151634 {
31560405de4Skz151634 	DRM_DEVICE;
31660405de4Skz151634 	drm_set_version_t sv;
31760405de4Skz151634 	drm_set_version_t retv;
31860405de4Skz151634 	int if_version;
31960405de4Skz151634 
320*d0538f66Scg149915 	DRM_COPYFROM_WITH_RETURN(&sv, (void *)data, sizeof (sv));
32160405de4Skz151634 
32260405de4Skz151634 	retv.drm_di_major = DRM_IF_MAJOR;
32360405de4Skz151634 	retv.drm_di_minor = DRM_IF_MINOR;
324*d0538f66Scg149915 	retv.drm_dd_major = dev->driver->driver_major;
325*d0538f66Scg149915 	retv.drm_dd_minor = dev->driver->driver_minor;
32660405de4Skz151634 
327*d0538f66Scg149915 	DRM_COPYTO_WITH_RETURN((void *)data, &retv, sizeof (sv));
32860405de4Skz151634 
32960405de4Skz151634 	if (sv.drm_di_major != -1) {
33060405de4Skz151634 		if (sv.drm_di_major != DRM_IF_MAJOR ||
33160405de4Skz151634 		    sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
332*d0538f66Scg149915 			return (EINVAL);
33360405de4Skz151634 		if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
33460405de4Skz151634 		dev->if_version = DRM_MAX(if_version, dev->if_version);
33560405de4Skz151634 		if (sv.drm_di_minor >= 1) {
33660405de4Skz151634 			/*
33760405de4Skz151634 			 * Version 1.1 includes tying of DRM to specific device
33860405de4Skz151634 			 */
33960405de4Skz151634 			(void) drm_set_busid(dev);
34060405de4Skz151634 		}
34160405de4Skz151634 	}
34260405de4Skz151634 
34360405de4Skz151634 	if (sv.drm_dd_major != -1) {
344*d0538f66Scg149915 		if (sv.drm_dd_major != dev->driver->driver_major ||
345*d0538f66Scg149915 		    sv.drm_dd_minor < 0 ||
346*d0538f66Scg149915 		    sv.drm_dd_minor > dev->driver->driver_minor)
347*d0538f66Scg149915 			return (EINVAL);
34860405de4Skz151634 	}
34960405de4Skz151634 	return (0);
35060405de4Skz151634 }
35160405de4Skz151634 
35260405de4Skz151634 
35360405de4Skz151634 /*ARGSUSED*/
35460405de4Skz151634 int
drm_noop(DRM_IOCTL_ARGS)35560405de4Skz151634 drm_noop(DRM_IOCTL_ARGS)
35660405de4Skz151634 {
35760405de4Skz151634 	DRM_DEBUG("drm_noop\n");
35860405de4Skz151634 	return (0);
35960405de4Skz151634 }
36060405de4Skz151634 
36160405de4Skz151634 /*ARGSUSED*/
36260405de4Skz151634 int
drm_version(DRM_IOCTL_ARGS)36360405de4Skz151634 drm_version(DRM_IOCTL_ARGS)
36460405de4Skz151634 {
36560405de4Skz151634 	DRM_DEVICE;
36660405de4Skz151634 	drm_version_t version;
367*d0538f66Scg149915 	size_t len;
36860405de4Skz151634 
369*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
37060405de4Skz151634 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
371*d0538f66Scg149915 		drm_version_32_t version32;
37260405de4Skz151634 
373*d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&version32,
374*d0538f66Scg149915 		    (void *)data, sizeof (drm_version_32_t));
37560405de4Skz151634 		version.name_len = version32.name_len;
376*d0538f66Scg149915 		version.name = (char *)(uintptr_t)version32.name;
37760405de4Skz151634 		version.date_len = version32.date_len;
378*d0538f66Scg149915 		version.date = (char *)(uintptr_t)version32.date;
37960405de4Skz151634 		version.desc_len = version32.desc_len;
380*d0538f66Scg149915 		version.desc = (char *)(uintptr_t)version32.desc;
38160405de4Skz151634 	} else
382*d0538f66Scg149915 #endif
383*d0538f66Scg149915 		DRM_COPYFROM_WITH_RETURN(&version, (void *)data,
384*d0538f66Scg149915 		    sizeof (version));
38560405de4Skz151634 
38660405de4Skz151634 #define	DRM_COPY(name, value)                                         \
38760405de4Skz151634 	len = strlen(value);                                          \
38860405de4Skz151634 	if (len > name##_len) len = name##_len;                       \
38960405de4Skz151634 		name##_len = strlen(value);                                   \
39060405de4Skz151634 	if (len && name) {                                            \
39160405de4Skz151634 		if (DRM_COPY_TO_USER(name, value, len))             \
392*d0538f66Scg149915 			return (EFAULT);                         \
39360405de4Skz151634 	}
39460405de4Skz151634 
395*d0538f66Scg149915 	version.version_major = dev->driver->driver_major;
396*d0538f66Scg149915 	version.version_minor = dev->driver->driver_minor;
397*d0538f66Scg149915 	version.version_patchlevel = dev->driver->driver_patchlevel;
39860405de4Skz151634 
399*d0538f66Scg149915 	DRM_COPY(version.name, dev->driver->driver_name);
400*d0538f66Scg149915 	DRM_COPY(version.date, dev->driver->driver_date);
401*d0538f66Scg149915 	DRM_COPY(version.desc, dev->driver->driver_desc);
40260405de4Skz151634 
403*d0538f66Scg149915 #ifdef	_MULTI_DATAMODEL
40460405de4Skz151634 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
405*d0538f66Scg149915 		drm_version_32_t version32;
40660405de4Skz151634 
40760405de4Skz151634 		version32.version_major = version.version_major;
40860405de4Skz151634 		version32.version_minor = version.version_minor;
40960405de4Skz151634 		version32.version_patchlevel = version.version_patchlevel;
410*d0538f66Scg149915 		version32.name_len = (uint32_t)version.name_len;
41160405de4Skz151634 		version32.name = (caddr32_t)(uintptr_t)version.name;
412*d0538f66Scg149915 		version32.date_len = (uint32_t)version.date_len;
41360405de4Skz151634 		version32.date = (caddr32_t)(uintptr_t)version.date;
414*d0538f66Scg149915 		version32.desc_len = (uint32_t)version.desc_len;
41560405de4Skz151634 		version32.desc = (caddr32_t)(uintptr_t)version.desc;
416*d0538f66Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &version32,
417*d0538f66Scg149915 		    sizeof (drm_version_32_t));
41860405de4Skz151634 	} else
419*d0538f66Scg149915 #endif
420*d0538f66Scg149915 		DRM_COPYTO_WITH_RETURN((void *)data, &version,
421*d0538f66Scg149915 		    sizeof (version));
42260405de4Skz151634 
42360405de4Skz151634 	return (0);
42460405de4Skz151634 }
425