7622 Separate DRM+AGP devlinks stuff into its own module
[unleashed.git] / usr / src / cmd / devfsadm / i386 / drm_link_i386.c
blobab29ab7899cf88251b62536d489dac922b14aeae
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Joyent, Inc. All rights reserved.
27 #include <regex.h>
28 #include <devfsadm.h>
29 #include <stdio.h>
30 #include <strings.h>
31 #include <stdlib.h>
32 #include <limits.h>
33 #include <ctype.h>
36 * Note: separate from misc_link_i386.c because this will later
37 * move to the gfx-drm gate.
40 static int agp_process(di_minor_t minor, di_node_t node);
41 static int drm_node(di_minor_t minor, di_node_t node);
43 static devfsadm_create_t drm_cbt[] = {
44 { "drm", "ddi_display:drm", NULL,
45 TYPE_EXACT, ILEVEL_0, drm_node
47 { "agp", "ddi_agp:pseudo", NULL,
48 TYPE_EXACT, ILEVEL_0, agp_process
50 { "agp", "ddi_agp:target", NULL,
51 TYPE_EXACT, ILEVEL_0, agp_process
53 { "agp", "ddi_agp:cpugart", NULL,
54 TYPE_EXACT, ILEVEL_0, agp_process
56 { "agp", "ddi_agp:master", NULL,
57 TYPE_EXACT, ILEVEL_0, agp_process
61 DEVFSADM_CREATE_INIT_V0(drm_cbt);
64 * For debugging, run devfsadm like this:
65 * devfsadm -V drm_mid -V devfsadm:enum -c drm
67 static char *debug_mid = "drm_mid";
69 typedef enum {
70 DRIVER_AGPPSEUDO = 0,
71 DRIVER_AGPTARGET,
72 DRIVER_CPUGART,
73 DRIVER_AGPMASTER_DRM_I915,
74 DRIVER_AGPMASTER_DRM_RADEON,
75 DRIVER_AGPMASTER_VGATEXT,
76 DRIVER_UNKNOWN
77 } driver_defs_t;
79 typedef struct {
80 char *driver_name;
81 int index;
82 } driver_name_table_entry_t;
84 static driver_name_table_entry_t driver_name_table[] = {
85 { "agpgart", DRIVER_AGPPSEUDO },
86 { "agptarget", DRIVER_AGPTARGET },
87 { "amd64_gart", DRIVER_CPUGART },
88 /* AGP master device managed by drm driver */
89 { "i915", DRIVER_AGPMASTER_DRM_I915 },
90 { "radeon", DRIVER_AGPMASTER_DRM_RADEON },
91 { "vgatext", DRIVER_AGPMASTER_VGATEXT },
92 { NULL, DRIVER_UNKNOWN }
95 static devfsadm_enumerate_t agptarget_rules[1] =
96 { "^agp$/^agptarget([0-9]+)$", 1, MATCH_ALL };
97 static devfsadm_enumerate_t cpugart_rules[1] =
98 { "^agp$/^cpugart([0-9]+)$", 1, MATCH_ALL };
99 static devfsadm_enumerate_t agpmaster_rules[1] =
100 { "^agp$/^agpmaster([0-9]+)$", 1, MATCH_ALL };
101 static devfsadm_enumerate_t drm_rules[1] =
102 { "^dri$/^card([0-9]+)$", 1, MATCH_ALL };
106 * HOT auto cleanup of drm+agp links not desired.
108 static devfsadm_remove_t drm_remove_cbt[] = {
109 { "agp", "^agpgart$", RM_POST,
110 ILEVEL_0, devfsadm_rm_all
112 { "agp", "^agp/agpmaster[0-9]+$", RM_POST,
113 ILEVEL_0, devfsadm_rm_all
115 { "agp", "^agp/agptarget[0-9]+$", RM_POST,
116 ILEVEL_0, devfsadm_rm_all
118 { "agp", "^agp/cpugart[0-9]+$", RM_POST,
119 ILEVEL_0, devfsadm_rm_all
121 { "drm", "^dri/card[0-9]+$", RM_POST,
122 ILEVEL_0, devfsadm_rm_all
126 DEVFSADM_REMOVE_INIT_V0(drm_remove_cbt);
128 static int
129 agp_process(di_minor_t minor, di_node_t node)
131 char *minor_nm, *drv_nm;
132 char *devfspath;
133 char *I_path, *p_path, *buf;
134 char *name = (char *)NULL;
135 int i, index;
136 devfsadm_enumerate_t rules[1];
138 minor_nm = di_minor_name(minor);
139 drv_nm = di_driver_name(node);
141 if ((minor_nm == NULL) || (drv_nm == NULL)) {
142 return (DEVFSADM_CONTINUE);
145 devfsadm_print(debug_mid, "agp_process: minor=%s node=%s\n",
146 minor_nm, di_node_name(node));
148 devfspath = di_devfs_path(node);
149 if (devfspath == NULL) {
150 devfsadm_print(debug_mid, "agp_process: devfspath is NULL\n");
151 return (DEVFSADM_CONTINUE);
154 I_path = (char *)malloc(PATH_MAX);
156 if (I_path == NULL) {
157 di_devfs_path_free(devfspath);
158 devfsadm_print(debug_mid, "agp_process: malloc failed\n");
159 return (DEVFSADM_CONTINUE);
162 p_path = (char *)malloc(PATH_MAX);
164 if (p_path == NULL) {
165 devfsadm_print(debug_mid, "agp_process: malloc failed\n");
166 di_devfs_path_free(devfspath);
167 free(I_path);
168 return (DEVFSADM_CONTINUE);
171 (void) strlcpy(p_path, devfspath, PATH_MAX);
172 (void) strlcat(p_path, ":", PATH_MAX);
173 (void) strlcat(p_path, minor_nm, PATH_MAX);
174 di_devfs_path_free(devfspath);
176 devfsadm_print(debug_mid, "agp_process: path %s\n", p_path);
178 for (i = 0; ; i++) {
179 if ((driver_name_table[i].driver_name == NULL) ||
180 (strcmp(drv_nm, driver_name_table[i].driver_name) == 0)) {
181 index = driver_name_table[i].index;
182 break;
185 switch (index) {
186 case DRIVER_AGPPSEUDO:
187 devfsadm_print(debug_mid,
188 "agp_process: psdeudo driver name\n");
189 name = "agpgart";
190 (void) snprintf(I_path, PATH_MAX, "%s", name);
191 devfsadm_print(debug_mid,
192 "mklink %s -> %s\n", I_path, p_path);
194 (void) devfsadm_mklink(I_path, node, minor, 0);
196 free(I_path);
197 free(p_path);
198 return (DEVFSADM_CONTINUE);
199 case DRIVER_AGPTARGET:
200 devfsadm_print(debug_mid,
201 "agp_process: target driver name\n");
202 rules[0] = agptarget_rules[0];
203 name = "agptarget";
204 break;
205 case DRIVER_CPUGART:
206 devfsadm_print(debug_mid,
207 "agp_process: cpugart driver name\n");
208 rules[0] = cpugart_rules[0];
209 name = "cpugart";
210 break;
211 case DRIVER_AGPMASTER_DRM_I915:
212 case DRIVER_AGPMASTER_DRM_RADEON:
213 case DRIVER_AGPMASTER_VGATEXT:
214 devfsadm_print(debug_mid,
215 "agp_process: agpmaster driver name\n");
216 rules[0] = agpmaster_rules[0];
217 name = "agpmaster";
218 break;
219 case DRIVER_UNKNOWN:
220 devfsadm_print(debug_mid,
221 "agp_process: unknown driver name=%s\n", drv_nm);
222 free(I_path);
223 free(p_path);
224 return (DEVFSADM_CONTINUE);
227 if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
228 devfsadm_print(debug_mid, "agp_process: exit/coninue\n");
229 free(I_path);
230 free(p_path);
231 return (DEVFSADM_CONTINUE);
235 (void) snprintf(I_path, PATH_MAX, "agp/%s%s", name, buf);
237 devfsadm_print(debug_mid, "agp_process: p_path=%s buf=%s\n",
238 p_path, buf);
240 free(buf);
242 devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
244 (void) devfsadm_mklink(I_path, node, minor, 0);
246 free(p_path);
247 free(I_path);
249 return (DEVFSADM_CONTINUE);
252 static int
253 drm_node(di_minor_t minor, di_node_t node)
255 char *minor_nm, *drv_nm;
256 char *devfspath;
257 char *I_path, *p_path, *buf;
258 char *name = "card";
260 minor_nm = di_minor_name(minor);
261 drv_nm = di_driver_name(node);
262 if ((minor_nm == NULL) || (drv_nm == NULL)) {
263 return (DEVFSADM_CONTINUE);
266 devfsadm_print(debug_mid, "drm_node: minor=%s node=%s type=%s\n",
267 minor_nm, di_node_name(node), di_minor_nodetype(minor));
269 devfspath = di_devfs_path(node);
270 if (devfspath == NULL) {
271 devfsadm_print(debug_mid, "drm_node: devfspath is NULL\n");
272 return (DEVFSADM_CONTINUE);
275 I_path = (char *)malloc(PATH_MAX);
277 if (I_path == NULL) {
278 di_devfs_path_free(devfspath);
279 devfsadm_print(debug_mid, "drm_node: malloc failed\n");
280 return (DEVFSADM_CONTINUE);
283 p_path = (char *)malloc(PATH_MAX);
285 if (p_path == NULL) {
286 devfsadm_print(debug_mid, "drm_node: malloc failed\n");
287 di_devfs_path_free(devfspath);
288 free(I_path);
289 return (DEVFSADM_CONTINUE);
292 (void) strlcpy(p_path, devfspath, PATH_MAX);
293 (void) strlcat(p_path, ":", PATH_MAX);
294 (void) strlcat(p_path, minor_nm, PATH_MAX);
295 di_devfs_path_free(devfspath);
297 devfsadm_print(debug_mid, "drm_node: p_path %s\n", p_path);
299 if (devfsadm_enumerate_int(p_path, 0, &buf, drm_rules, 1)) {
300 free(p_path);
301 devfsadm_print(debug_mid, "drm_node: exit/coninue\n");
302 return (DEVFSADM_CONTINUE);
304 (void) snprintf(I_path, PATH_MAX, "dri/%s%s", name, buf);
306 devfsadm_print(debug_mid, "drm_node: p_path=%s buf=%s\n",
307 p_path, buf);
309 free(buf);
311 devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
312 (void) devfsadm_mklink(I_path, node, minor, 0);
314 free(p_path);
315 free(I_path);
317 return (0);