xref: /titanic_44/usr/src/cmd/devfsadm/i386/misc_link_i386.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <regex.h>
30 #include <devfsadm.h>
31 #include <stdio.h>
32 #include <strings.h>
33 #include <stdlib.h>
34 #include <limits.h>
35 #include <ctype.h>
36 
37 static int lp(di_minor_t minor, di_node_t node);
38 static int serial_dialout(di_minor_t minor, di_node_t node);
39 static int serial(di_minor_t minor, di_node_t node);
40 static int diskette(di_minor_t minor, di_node_t node);
41 static int vt00(di_minor_t minor, di_node_t node);
42 static int kdmouse(di_minor_t minor, di_node_t node);
43 static int bmc(di_minor_t minor, di_node_t node);
44 static int agp_process(di_minor_t minor, di_node_t node);
45 
46 static devfsadm_create_t misc_cbt[] = {
47 	{ "vt00", "ddi_display", NULL,
48 	    TYPE_EXACT, ILEVEL_0,	vt00
49 	},
50 	{ "mouse", "ddi_mouse", "mouse8042",
51 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, kdmouse
52 	},
53 	{ "pseudo", "ddi_pseudo", "bmc",
54 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, bmc,
55 	},
56 	{ "disk",  "ddi_block:diskette", NULL,
57 	    TYPE_EXACT, ILEVEL_1, diskette
58 	},
59 	{ "parallel",  "ddi_printer", NULL,
60 	    TYPE_EXACT, ILEVEL_1, lp
61 	},
62 	{ "serial", "ddi_serial:mb", NULL,
63 	    TYPE_EXACT, ILEVEL_1, serial
64 	},
65 	{ "serial",  "ddi_serial:dialout,mb", NULL,
66 	    TYPE_EXACT, ILEVEL_1, serial_dialout
67 	},
68 	{"agp", "ddi_agp:pseudo", NULL,
69 	    TYPE_EXACT, ILEVEL_0, agp_process
70 	},
71 	{"agp", "ddi_agp:target", NULL,
72 	    TYPE_EXACT, ILEVEL_0, agp_process
73 	},
74 	{"agp", "ddi_agp:cpugart", NULL,
75 	    TYPE_EXACT, ILEVEL_0, agp_process
76 	},
77 	{"agp", "ddi_agp:master", NULL,
78 	    TYPE_EXACT, ILEVEL_0, agp_process
79 	}
80 };
81 
82 DEVFSADM_CREATE_INIT_V0(misc_cbt);
83 
84 static char *debug_mid = "agp_mid";
85 
86 typedef enum {
87 	DRIVER_AGPPSEUDO = 0,
88 	DRIVER_AGPTARGET,
89 	DRIVER_CPUGART,
90 	DRIVER_AGPMASTER,
91 	DRIVER_UNKNOWN
92 } driver_defs_t;
93 
94 typedef struct {
95 	char	*driver_name;
96 	int	index;
97 } driver_name_table_entry_t;
98 
99 static driver_name_table_entry_t driver_name_table[] = {
100 	{ "agpgart",		DRIVER_AGPPSEUDO },
101 	{ "agptarget",		DRIVER_AGPTARGET },
102 	{ "amd64_gart",		DRIVER_CPUGART },
103 	{ "vgatext",		DRIVER_AGPMASTER },
104 	{ NULL,			DRIVER_UNKNOWN }
105 };
106 
107 static devfsadm_enumerate_t agptarget_rules[1] =
108 	{ "^agp$/^agptarget([0-9]+)$", 1, MATCH_ALL };
109 static devfsadm_enumerate_t cpugart_rules[1] =
110 	{ "^agp$/^cpugart([0-9]+)$", 1, MATCH_ALL };
111 static devfsadm_enumerate_t agpmaster_rules[1] =
112 	{  "^agp$/^agpmaster([0-9]+)$", 1, MATCH_ALL };
113 
114 static devfsadm_remove_t misc_remove_cbt[] = {
115 	{ "vt", "vt[0-9][0-9]", RM_PRE|RM_ALWAYS,
116 		ILEVEL_0, devfsadm_rm_all
117 	}
118 };
119 
120 DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt);
121 
122 /*
123  * Handles minor node type "ddi_display", in addition to generic processing
124  * done by display().
125  *
126  * This creates a /dev/vt00 link to /dev/fb, for backwards compatibility.
127  */
128 /* ARGSUSED */
129 int
130 vt00(di_minor_t minor, di_node_t node)
131 {
132 	(void) devfsadm_secondary_link("vt00", "fb", 0);
133 	return (DEVFSADM_CONTINUE);
134 }
135 
136 /*
137  * type=ddi_block:diskette;addr=0,0;minor=c        diskette
138  * type=ddi_block:diskette;addr=0,0;minor=c,raw    rdiskette
139  * type=ddi_block:diskette;addr1=0;minor=c diskette\A2
140  * type=ddi_block:diskette;addr1=0;minor=c,raw     rdiskette\A2
141  */
142 static int
143 diskette(di_minor_t minor, di_node_t node)
144 {
145 	char *a2;
146 	char link[PATH_MAX];
147 	char *addr = di_bus_addr(node);
148 	char *mn = di_minor_name(minor);
149 
150 	if (strcmp(addr, "0,0") == 0) {
151 		if (strcmp(mn, "c") == 0) {
152 			(void) devfsadm_mklink("diskette", node, minor, 0);
153 		} else if (strcmp(mn, "c,raw") == 0) {
154 			(void) devfsadm_mklink("rdiskette", node, minor, 0);
155 		}
156 
157 	}
158 
159 	if (addr[0] == '0') {
160 		if ((a2 = strchr(addr, ',')) != NULL) {
161 			a2++;
162 			if (strcmp(mn, "c") == 0) {
163 				(void) strcpy(link, "diskette");
164 				(void) strcat(link, a2);
165 				(void) devfsadm_mklink(link, node, minor, 0);
166 			} else if (strcmp(mn, "c,raw") == 0) {
167 				(void) strcpy(link, "rdiskette");
168 				(void) strcat(link, a2);
169 				(void) devfsadm_mklink(link, node, minor, 0);
170 			}
171 		}
172 	}
173 
174 	return (DEVFSADM_CONTINUE);
175 }
176 
177 /*
178  * type=ddi_printer;name=lp;addr=1,3bc      lp0
179  * type=ddi_printer;name=lp;addr=1,378      lp1
180  * type=ddi_printer;name=lp;addr=1,278      lp2
181  */
182 static int
183 lp(di_minor_t minor, di_node_t node)
184 {
185 	char *addr = di_bus_addr(node);
186 	char *buf;
187 	char path[PATH_MAX + 1];
188 	devfsadm_enumerate_t rules[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL};
189 
190 	if (strcmp(addr, "1,3bc") == 0) {
191 		(void) devfsadm_mklink("lp0", node, minor, 0);
192 
193 	} else if (strcmp(addr, "1,378") == 0) {
194 		(void) devfsadm_mklink("lp1", node, minor, 0);
195 
196 	} else if (strcmp(addr, "1,278") == 0) {
197 		(void) devfsadm_mklink("lp2", node, minor, 0);
198 	}
199 
200 	if (strcmp(di_driver_name(node), "ecpp") != 0) {
201 		return (DEVFSADM_CONTINUE);
202 	}
203 
204 	if ((buf = di_devfs_path(node)) == NULL) {
205 		return (DEVFSADM_CONTINUE);
206 	}
207 
208 	(void) snprintf(path, sizeof (path), "%s:%s",
209 	    buf, di_minor_name(minor));
210 
211 	di_devfs_path_free(buf);
212 
213 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
214 		return (DEVFSADM_CONTINUE);
215 	}
216 
217 	(void) snprintf(path, sizeof (path), "ecpp%s", buf);
218 	free(buf);
219 	(void) devfsadm_mklink(path, node, minor, 0);
220 	return (DEVFSADM_CONTINUE);
221 }
222 
223 /*
224  * type=ddi_serial:mb;minor=a      tty00
225  * type=ddi_serial:mb;minor=b      tty01
226  * type=ddi_serial:mb;minor=c      tty02
227  * type=ddi_serial:mb;minor=d      tty03
228  */
229 static int
230 serial(di_minor_t minor, di_node_t node)
231 {
232 
233 	char *mn = di_minor_name(minor);
234 	char link[PATH_MAX];
235 
236 	(void) strcpy(link, "tty");
237 	(void) strcat(link, mn);
238 	(void) devfsadm_mklink(link, node, minor, 0);
239 
240 	if (strcmp(mn, "a") == 0) {
241 		(void) devfsadm_mklink("tty00", node, minor, 0);
242 
243 	} else if (strcmp(mn, "b") == 0) {
244 		(void) devfsadm_mklink("tty01", node, minor, 0);
245 
246 	} else if (strcmp(mn, "c") == 0) {
247 		(void) devfsadm_mklink("tty02", node, minor, 0);
248 
249 	} else if (strcmp(mn, "d") == 0) {
250 		(void) devfsadm_mklink("tty03", node, minor, 0);
251 	}
252 	return (DEVFSADM_CONTINUE);
253 }
254 
255 /*
256  * type=ddi_serial:dialout,mb;minor=a,cu   ttyd0
257  * type=ddi_serial:dialout,mb;minor=b,cu   ttyd1
258  * type=ddi_serial:dialout,mb;minor=c,cu   ttyd2
259  * type=ddi_serial:dialout,mb;minor=d,cu   ttyd3
260  */
261 static int
262 serial_dialout(di_minor_t minor, di_node_t node)
263 {
264 	char *mn = di_minor_name(minor);
265 
266 	if (strcmp(mn, "a,cu") == 0) {
267 		(void) devfsadm_mklink("ttyd0", node, minor, 0);
268 		(void) devfsadm_mklink("cua0", node, minor, 0);
269 
270 	} else if (strcmp(mn, "b,cu") == 0) {
271 		(void) devfsadm_mklink("ttyd1", node, minor, 0);
272 		(void) devfsadm_mklink("cua1", node, minor, 0);
273 
274 	} else if (strcmp(mn, "c,cu") == 0) {
275 		(void) devfsadm_mklink("ttyd2", node, minor, 0);
276 		(void) devfsadm_mklink("cua2", node, minor, 0);
277 
278 	} else if (strcmp(mn, "d,cu") == 0) {
279 		(void) devfsadm_mklink("ttyd3", node, minor, 0);
280 		(void) devfsadm_mklink("cua3", node, minor, 0);
281 	}
282 	return (DEVFSADM_CONTINUE);
283 }
284 
285 static int
286 kdmouse(di_minor_t minor, di_node_t node)
287 {
288 	(void) devfsadm_mklink("kdmouse", node, minor, 0);
289 	return (DEVFSADM_CONTINUE);
290 }
291 
292 static int
293 bmc(di_minor_t minor, di_node_t node)
294 {
295 	(void) devfsadm_mklink("bmc", node, minor, 0);
296 	return (DEVFSADM_CONTINUE);
297 }
298 static int
299 agp_process(di_minor_t minor, di_node_t node)
300 {
301 	char *minor_nm, *drv_nm;
302 	char *devfspath;
303 	char *I_path, *p_path, *buf;
304 	char *name = (char *)NULL;
305 	int i, index;
306 	devfsadm_enumerate_t rules[1];
307 
308 	minor_nm = di_minor_name(minor);
309 	drv_nm = di_driver_name(node);
310 
311 	if ((minor_nm == NULL) || (drv_nm == NULL)) {
312 		return (DEVFSADM_CONTINUE);
313 	}
314 
315 	devfsadm_print(debug_mid, "agp_process: minor=%s node=%s\n",
316 		minor_nm, di_node_name(node));
317 
318 	devfspath = di_devfs_path(node);
319 	if (devfspath == NULL) {
320 		devfsadm_print(debug_mid, "agp_process: devfspath is NULL\n");
321 		return (DEVFSADM_CONTINUE);
322 	}
323 
324 	I_path = (char *)malloc(PATH_MAX);
325 
326 	if (I_path == NULL) {
327 		di_devfs_path_free(devfspath);
328 		devfsadm_print(debug_mid,  "agp_process: malloc failed\n");
329 		return (DEVFSADM_CONTINUE);
330 	}
331 
332 	p_path = (char *)malloc(PATH_MAX);
333 
334 	if (p_path == NULL) {
335 		devfsadm_print(debug_mid,  "agp_process: malloc failed\n");
336 		di_devfs_path_free(devfspath);
337 		free(I_path);
338 		return (DEVFSADM_CONTINUE);
339 	}
340 
341 	(void) strlcpy(p_path, devfspath, PATH_MAX);
342 	(void) strlcat(p_path, ":", PATH_MAX);
343 	(void) strlcat(p_path, minor_nm, PATH_MAX);
344 	di_devfs_path_free(devfspath);
345 
346 	devfsadm_print(debug_mid, "agp_process: path %s\n", p_path);
347 
348 	for (i = 0; ; i++) {
349 		if ((driver_name_table[i].driver_name == NULL) ||
350 		    (strcmp(drv_nm, driver_name_table[i].driver_name) == 0)) {
351 			index = driver_name_table[i].index;
352 			break;
353 		}
354 	}
355 	switch (index) {
356 	case DRIVER_AGPPSEUDO:
357 		devfsadm_print(debug_mid,
358 			    "agp_process: psdeudo driver name\n");
359 		name = "agpgart";
360 		(void) snprintf(I_path, PATH_MAX, "%s", name);
361 		devfsadm_print(debug_mid,
362 		    "mklink %s -> %s\n", I_path, p_path);
363 
364 		(void) devfsadm_mklink(I_path, node, minor, 0);
365 
366 		free(I_path);
367 		free(p_path);
368 		return (DEVFSADM_CONTINUE);
369 	case DRIVER_AGPTARGET:
370 		devfsadm_print(debug_mid,
371 			    "agp_process: target driver name\n");
372 		rules[0] = agptarget_rules[0];
373 		name = "agptarget";
374 		break;
375 	case DRIVER_CPUGART:
376 		devfsadm_print(debug_mid,
377 			    "agp_process: cpugart driver name\n");
378 		rules[0] = cpugart_rules[0];
379 		name = "cpugart";
380 		break;
381 	case DRIVER_AGPMASTER:
382 		devfsadm_print(debug_mid,
383 			    "agp_process: agpmaster driver name\n");
384 		rules[0] = agpmaster_rules[0];
385 		name = "agpmaster";
386 		break;
387 	case DRIVER_UNKNOWN:
388 		devfsadm_print(debug_mid,
389 			    "agp_process: unknown driver name=%s\n", drv_nm);
390 		free(I_path);
391 		free(p_path);
392 		return (DEVFSADM_CONTINUE);
393 	}
394 
395 	if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
396 		devfsadm_print(debug_mid, "agp_process: exit/coninue\n");
397 		free(I_path);
398 		free(p_path);
399 		return (DEVFSADM_CONTINUE);
400 	}
401 
402 
403 	(void) snprintf(I_path, PATH_MAX, "agp/%s%s", name, buf);
404 
405 	devfsadm_print(debug_mid, "agp_process: p_path=%s buf=%s\n",
406 		    p_path, buf);
407 
408 	free(buf);
409 
410 	devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
411 
412 	(void) devfsadm_mklink(I_path, node, minor, 0);
413 
414 	free(p_path);
415 	free(I_path);
416 
417 	return (DEVFSADM_CONTINUE);
418 }
419