xref: /titanic_50/usr/src/uts/common/io/drm/drm_auth.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
8  * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
9  */
10 /*
11  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
12  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
13  * All Rights Reserved.
14  *
15  * Permission is hereby granted, free of charge, to any person obtaining a
16  * copy of this software and associated documentation files (the "Software"),
17  * to deal in the Software without restriction, including without limitation
18  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19  * and/or sell copies of the Software, and to permit persons to whom the
20  * Software is furnished to do so, subject to the following conditions:
21  *
22  * The above copyright notice and this permission notice (including the next
23  * paragraph) shall be included in all copies or substantial portions of the
24  * Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
29  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
30  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
31  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
32  * OTHER DEALINGS IN THE SOFTWARE.
33  *
34  * Authors:
35  *    Rickard E. (Rik) Faith <faith@valinux.com>
36  *    Gareth Hughes <gareth@valinux.com>
37  *
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 #include "drmP.h"
43 
44 static int
45 drm_hash_magic(drm_magic_t magic)
46 {
47 	return (magic & (DRM_HASH_SIZE-1));
48 }
49 
50 drm_file_t *
51 drm_find_file(drm_device_t *dev, drm_magic_t magic)
52 {
53 	drm_file_t	  *retval = NULL;
54 	drm_magic_entry_t *pt;
55 	int		  hash;
56 
57 	hash = drm_hash_magic(magic);
58 	for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
59 		if (pt->magic == magic) {
60 			retval = pt->priv;
61 			break;
62 		}
63 	}
64 
65 	return (retval);
66 }
67 
68 static int
69 drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
70 {
71 	int		  hash;
72 	drm_magic_entry_t *entry;
73 
74 	hash = drm_hash_magic(magic);
75 	entry = drm_alloc(sizeof (*entry), DRM_MEM_MAGIC);
76 	if (!entry)
77 		return (ENOMEM);
78 	entry->magic = magic;
79 	entry->priv  = priv;
80 	entry->next  = NULL;
81 
82 	DRM_LOCK();
83 	if (dev->magiclist[hash].tail) {
84 		dev->magiclist[hash].tail->next = entry;
85 		dev->magiclist[hash].tail	= entry;
86 	} else {
87 		dev->magiclist[hash].head	= entry;
88 		dev->magiclist[hash].tail	= entry;
89 	}
90 	DRM_UNLOCK();
91 
92 	return (0);
93 }
94 
95 int
96 drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
97 {
98 	drm_magic_entry_t *prev = NULL;
99 	drm_magic_entry_t *pt;
100 	int		  hash;
101 
102 	DRM_DEBUG("drm_remove_magic : %d", magic);
103 	hash = drm_hash_magic(magic);
104 
105 	DRM_LOCK();
106 	for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
107 		if (pt->magic == magic) {
108 			if (dev->magiclist[hash].head == pt) {
109 				dev->magiclist[hash].head = pt->next;
110 			}
111 			if (dev->magiclist[hash].tail == pt) {
112 				dev->magiclist[hash].tail = prev;
113 			}
114 			if (prev) {
115 				prev->next = pt->next;
116 			}
117 			DRM_UNLOCK();
118 			drm_free(pt, sizeof (*pt), DRM_MEM_MAGIC);
119 			return (0);
120 		}
121 	}
122 	DRM_UNLOCK();
123 
124 	return (EINVAL);
125 }
126 
127 /*ARGSUSED*/
128 int
129 drm_getmagic(DRM_IOCTL_ARGS)
130 {
131 	DRM_DEVICE;
132 	static drm_magic_t sequence = 0;
133 	drm_auth_t auth;
134 
135 	/* Find unique magic */
136 	if (fpriv->magic) {
137 		auth.magic = fpriv->magic;
138 	} else {
139 		do {
140 			int old = sequence;
141 			auth.magic = old+1;
142 			if (!atomic_cmpset_int(&sequence, old, auth.magic))
143 				continue;
144 		} while (drm_find_file(dev, auth.magic));
145 		fpriv->magic = auth.magic;
146 		(void) drm_add_magic(dev, fpriv, auth.magic);
147 	}
148 
149 
150 	DRM_DEBUG("drm_getmagic: %u", auth.magic);
151 
152 	DRM_COPYTO_WITH_RETURN((void *)data, &auth, sizeof (auth));
153 
154 	return (0);
155 }
156 
157 /*ARGSUSED*/
158 int
159 drm_authmagic(DRM_IOCTL_ARGS)
160 {
161 	drm_auth_t	   auth;
162 	drm_file_t	   *file;
163 	DRM_DEVICE;
164 
165 	DRM_COPYFROM_WITH_RETURN(&auth, (void *)data, sizeof (auth));
166 
167 	if ((file = drm_find_file(dev, auth.magic))) {
168 		file->authenticated = 1;
169 		(void) drm_remove_magic(dev, auth.magic);
170 		return (0);
171 	}
172 	return (EINVAL);
173 }
174