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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Joyent, Inc. All rights reserved.
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";
73 DRIVER_AGPMASTER_DRM_I915
,
74 DRIVER_AGPMASTER_DRM_RADEON
,
75 DRIVER_AGPMASTER_VGATEXT
,
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
);
129 agp_process(di_minor_t minor
, di_node_t node
)
131 char *minor_nm
, *drv_nm
;
133 char *I_path
, *p_path
, *buf
;
134 char *name
= (char *)NULL
;
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
);
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
);
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
;
186 case DRIVER_AGPPSEUDO
:
187 devfsadm_print(debug_mid
,
188 "agp_process: psdeudo driver name\n");
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);
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];
206 devfsadm_print(debug_mid
,
207 "agp_process: cpugart driver name\n");
208 rules
[0] = cpugart_rules
[0];
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];
220 devfsadm_print(debug_mid
,
221 "agp_process: unknown driver name=%s\n", drv_nm
);
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");
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",
242 devfsadm_print(debug_mid
, "mklink %s -> %s\n", I_path
, p_path
);
244 (void) devfsadm_mklink(I_path
, node
, minor
, 0);
249 return (DEVFSADM_CONTINUE
);
253 drm_node(di_minor_t minor
, di_node_t node
)
255 char *minor_nm
, *drv_nm
;
257 char *I_path
, *p_path
, *buf
;
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
);
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)) {
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",
311 devfsadm_print(debug_mid
, "mklink %s -> %s\n", I_path
, p_path
);
312 (void) devfsadm_mklink(I_path
, node
, minor
, 0);