7622 Separate DRM+AGP devlinks stuff into its own module
[unleashed.git] / usr / src / cmd / devfsadm / i386 / misc_link_i386.c
blob84a24b1092a017e021b8544714359b79b9f2c861
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>
34 #include <sys/mc_amd.h>
35 #include <bsm/devalloc.h>
37 extern int system_labeled;
39 static int lp(di_minor_t minor, di_node_t node);
40 static int serial_dialout(di_minor_t minor, di_node_t node);
41 static int serial(di_minor_t minor, di_node_t node);
42 static int diskette(di_minor_t minor, di_node_t node);
43 static int vt00(di_minor_t minor, di_node_t node);
44 static int kdmouse(di_minor_t minor, di_node_t node);
45 static int ipmi(di_minor_t minor, di_node_t node);
46 static int smbios(di_minor_t minor, di_node_t node);
47 static int mc_node(di_minor_t minor, di_node_t node);
48 static int xsvc(di_minor_t minor, di_node_t node);
49 static int srn(di_minor_t minor, di_node_t node);
50 static int ucode(di_minor_t minor, di_node_t node);
51 static int heci(di_minor_t minor, di_node_t node);
54 static devfsadm_create_t misc_cbt[] = {
55 { "vt00", "ddi_display", NULL,
56 TYPE_EXACT, ILEVEL_0, vt00
58 { "mouse", "ddi_mouse", "mouse8042",
59 TYPE_EXACT | DRV_EXACT, ILEVEL_0, kdmouse
61 { "pseudo", "ddi_pseudo", "ipmi",
62 TYPE_EXACT | DRV_EXACT, ILEVEL_0, ipmi,
64 { "pseudo", "ddi_pseudo", "smbios",
65 TYPE_EXACT | DRV_EXACT, ILEVEL_1, smbios,
67 /* floppies share the same class, but not link regex, as hard disks */
68 { "disk", "ddi_block:diskette", NULL,
69 TYPE_EXACT, ILEVEL_1, diskette
71 { "parallel", "ddi_printer", NULL,
72 TYPE_EXACT, ILEVEL_1, lp
74 { "serial", "ddi_serial:mb", NULL,
75 TYPE_EXACT, ILEVEL_1, serial
77 { "serial", "ddi_serial:dialout,mb", NULL,
78 TYPE_EXACT, ILEVEL_1, serial_dialout
80 { "pseudo", "ddi_pseudo", NULL,
81 TYPE_EXACT, ILEVEL_0, xsvc
83 { "pseudo", "ddi_pseudo", NULL,
84 TYPE_EXACT, ILEVEL_0, srn
86 { "memory-controller", "ddi_mem_ctrl", NULL,
87 TYPE_EXACT, ILEVEL_0, mc_node
89 { "pseudo", "ddi_pseudo", "ucode",
90 TYPE_EXACT | DRV_EXACT, ILEVEL_0, ucode,
92 { "pseudo", "ddi_pseudo", "heci",
93 TYPE_EXACT | DRV_EXACT, ILEVEL_0, heci,
97 DEVFSADM_CREATE_INIT_V0(misc_cbt);
99 static devfsadm_remove_t misc_remove_cbt[] = {
100 { "vt", "vt[0-9][0-9]", RM_PRE|RM_ALWAYS,
101 ILEVEL_0, devfsadm_rm_all
103 { "pseudo", "^ucode$", RM_ALWAYS | RM_PRE | RM_HOT,
104 ILEVEL_0, devfsadm_rm_all
106 { "mouse", "^kdmouse$", RM_ALWAYS | RM_PRE,
107 ILEVEL_0, devfsadm_rm_all
109 { "disk", "^(diskette|rdiskette)([0-9]*)$",
110 RM_ALWAYS | RM_PRE, ILEVEL_1, devfsadm_rm_all
112 { "parallel", "^(lp|ecpp)([0-9]+)$", RM_ALWAYS | RM_PRE,
113 ILEVEL_1, devfsadm_rm_all
115 { "serial", "^(tty|ttyd)([0-9]+)$", RM_ALWAYS | RM_PRE,
116 ILEVEL_1, devfsadm_rm_all
118 { "serial", "^tty[a-z]$", RM_ALWAYS | RM_PRE,
119 ILEVEL_1, devfsadm_rm_all
123 DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt);
126 * Handles minor node type "ddi_display", in addition to generic processing
127 * done by display().
129 * This creates a /dev/vt00 link to /dev/fb, for backwards compatibility.
131 /* ARGSUSED */
133 vt00(di_minor_t minor, di_node_t node)
135 (void) devfsadm_secondary_link("vt00", "fb", 0);
136 return (DEVFSADM_CONTINUE);
140 * type=ddi_block:diskette;addr=0,0;minor=c diskette
141 * type=ddi_block:diskette;addr=0,0;minor=c,raw rdiskette
142 * type=ddi_block:diskette;addr1=0;minor=c diskette\A2
143 * type=ddi_block:diskette;addr1=0;minor=c,raw rdiskette\A2
145 static int
146 diskette(di_minor_t minor, di_node_t node)
148 int flags = 0;
149 char *a2;
150 char link[PATH_MAX];
151 char *addr = di_bus_addr(node);
152 char *mn = di_minor_name(minor);
154 if (system_labeled)
155 flags = DA_ADD|DA_FLOPPY;
157 if (strcmp(addr, "0,0") == 0) {
158 if (strcmp(mn, "c") == 0) {
159 (void) devfsadm_mklink("diskette", node, minor, flags);
160 } else if (strcmp(mn, "c,raw") == 0) {
161 (void) devfsadm_mklink("rdiskette", node, minor, flags);
166 if (addr[0] == '0') {
167 if ((a2 = strchr(addr, ',')) != NULL) {
168 a2++;
169 if (strcmp(mn, "c") == 0) {
170 (void) strcpy(link, "diskette");
171 (void) strcat(link, a2);
172 (void) devfsadm_mklink(link, node, minor,
173 flags);
174 } else if (strcmp(mn, "c,raw") == 0) {
175 (void) strcpy(link, "rdiskette");
176 (void) strcat(link, a2);
177 (void) devfsadm_mklink(link, node, minor,
178 flags);
183 return (DEVFSADM_CONTINUE);
187 * type=ddi_printer;name=lp;addr=1,3bc lp0
188 * type=ddi_printer;name=lp;addr=1,378 lp1
189 * type=ddi_printer;name=lp;addr=1,278 lp2
191 static int
192 lp(di_minor_t minor, di_node_t node)
194 char *addr = di_bus_addr(node);
195 char *buf;
196 char path[PATH_MAX + 1];
197 devfsadm_enumerate_t rules[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL};
199 if (strcmp(addr, "1,3bc") == 0) {
200 (void) devfsadm_mklink("lp0", node, minor, 0);
202 } else if (strcmp(addr, "1,378") == 0) {
203 (void) devfsadm_mklink("lp1", node, minor, 0);
205 } else if (strcmp(addr, "1,278") == 0) {
206 (void) devfsadm_mklink("lp2", node, minor, 0);
209 if (strcmp(di_driver_name(node), "ecpp") != 0) {
210 return (DEVFSADM_CONTINUE);
213 if ((buf = di_devfs_path(node)) == NULL) {
214 return (DEVFSADM_CONTINUE);
217 (void) snprintf(path, sizeof (path), "%s:%s",
218 buf, di_minor_name(minor));
220 di_devfs_path_free(buf);
222 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
223 return (DEVFSADM_CONTINUE);
226 (void) snprintf(path, sizeof (path), "ecpp%s", buf);
227 free(buf);
228 (void) devfsadm_mklink(path, node, minor, 0);
229 return (DEVFSADM_CONTINUE);
233 * type=ddi_serial:mb;minor=a tty00
234 * type=ddi_serial:mb;minor=b tty01
235 * type=ddi_serial:mb;minor=c tty02
236 * type=ddi_serial:mb;minor=d tty03
238 static int
239 serial(di_minor_t minor, di_node_t node)
242 char *mn = di_minor_name(minor);
243 char link[PATH_MAX];
245 (void) strcpy(link, "tty");
246 (void) strcat(link, mn);
247 (void) devfsadm_mklink(link, node, minor, 0);
249 if (strcmp(mn, "a") == 0) {
250 (void) devfsadm_mklink("tty00", node, minor, 0);
252 } else if (strcmp(mn, "b") == 0) {
253 (void) devfsadm_mklink("tty01", node, minor, 0);
255 } else if (strcmp(mn, "c") == 0) {
256 (void) devfsadm_mklink("tty02", node, minor, 0);
258 } else if (strcmp(mn, "d") == 0) {
259 (void) devfsadm_mklink("tty03", node, minor, 0);
261 return (DEVFSADM_CONTINUE);
265 * type=ddi_serial:dialout,mb;minor=a,cu ttyd0
266 * type=ddi_serial:dialout,mb;minor=b,cu ttyd1
267 * type=ddi_serial:dialout,mb;minor=c,cu ttyd2
268 * type=ddi_serial:dialout,mb;minor=d,cu ttyd3
270 static int
271 serial_dialout(di_minor_t minor, di_node_t node)
273 char *mn = di_minor_name(minor);
275 if (strcmp(mn, "a,cu") == 0) {
276 (void) devfsadm_mklink("ttyd0", node, minor, 0);
277 (void) devfsadm_mklink("cua0", node, minor, 0);
279 } else if (strcmp(mn, "b,cu") == 0) {
280 (void) devfsadm_mklink("ttyd1", node, minor, 0);
281 (void) devfsadm_mklink("cua1", node, minor, 0);
283 } else if (strcmp(mn, "c,cu") == 0) {
284 (void) devfsadm_mklink("ttyd2", node, minor, 0);
285 (void) devfsadm_mklink("cua2", node, minor, 0);
287 } else if (strcmp(mn, "d,cu") == 0) {
288 (void) devfsadm_mklink("ttyd3", node, minor, 0);
289 (void) devfsadm_mklink("cua3", node, minor, 0);
291 return (DEVFSADM_CONTINUE);
294 static int
295 kdmouse(di_minor_t minor, di_node_t node)
297 (void) devfsadm_mklink("kdmouse", node, minor, 0);
298 return (DEVFSADM_CONTINUE);
301 static int
302 ipmi(di_minor_t minor, di_node_t node)
305 * Follow convention from other systems, and include an instance#,
306 * even though there will only be one.
308 (void) devfsadm_mklink("ipmi0", node, minor, 0);
309 return (DEVFSADM_CONTINUE);
312 static int
313 smbios(di_minor_t minor, di_node_t node)
315 (void) devfsadm_mklink("smbios", node, minor, 0);
316 return (DEVFSADM_CONTINUE);
320 * /dev/mc/mc<chipid> -> /devices/.../pci1022,1102@<chipid+24>,2:mc-amd
322 static int
323 mc_node(di_minor_t minor, di_node_t node)
325 const char *minorname = di_minor_name(minor);
326 const char *busaddr = di_bus_addr(node);
327 char linkpath[PATH_MAX];
328 int unitaddr;
329 char *c;
331 if (minorname == NULL || busaddr == NULL)
332 return (DEVFSADM_CONTINUE);
334 errno = 0;
335 unitaddr = strtol(busaddr, &c, 16);
337 if (errno != 0)
338 return (DEVFSADM_CONTINUE);
340 if (unitaddr == 0) {
341 (void) snprintf(linkpath, sizeof (linkpath), "mc/mc");
342 } else if (unitaddr >= MC_AMD_DEV_OFFSET) {
343 (void) snprintf(linkpath, sizeof (linkpath), "mc/mc%u",
344 unitaddr - MC_AMD_DEV_OFFSET);
345 } else {
346 (void) snprintf(linkpath, sizeof (linkpath), "mc/mc%u",
347 minor->dev_minor);
349 (void) devfsadm_mklink(linkpath, node, minor, 0);
350 return (DEVFSADM_CONTINUE);
354 * Creates \M0 devlink for xsvc node
356 static int
357 xsvc(di_minor_t minor, di_node_t node)
359 char *mn;
361 if (strcmp(di_node_name(node), "xsvc") != 0)
362 return (DEVFSADM_CONTINUE);
364 mn = di_minor_name(minor);
365 if (mn == NULL)
366 return (DEVFSADM_CONTINUE);
368 (void) devfsadm_mklink(mn, node, minor, 0);
369 return (DEVFSADM_CONTINUE);
373 * Creates \M0 devlink for srn device
375 static int
376 srn(di_minor_t minor, di_node_t node)
378 char *mn;
380 if (strcmp(di_node_name(node), "srn") != 0)
381 return (DEVFSADM_CONTINUE);
383 mn = di_minor_name(minor);
384 if (mn == NULL)
385 return (DEVFSADM_CONTINUE);
387 (void) devfsadm_mklink(mn, node, minor, 0);
388 return (DEVFSADM_CONTINUE);
392 * /dev/ucode -> /devices/pseudo/ucode@0:ucode
394 static int
395 ucode(di_minor_t minor, di_node_t node)
397 (void) devfsadm_mklink("ucode", node, minor, 0);
398 return (DEVFSADM_CONTINUE);
401 static int
402 heci(di_minor_t minor, di_node_t node)
404 if (strcmp(di_minor_name(minor), "AMT") == 0) {
405 (void) devfsadm_mklink("heci", node, minor, 0);
407 return (DEVFSADM_CONTINUE);