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.
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
);
53 static devfsadm_create_t misc_cbt
[] = {
54 { "vt00", "ddi_display", NULL
,
55 TYPE_EXACT
, ILEVEL_0
, vt00
57 { "mouse", "ddi_mouse", "mouse8042",
58 TYPE_EXACT
| DRV_EXACT
, ILEVEL_0
, kdmouse
60 { "pseudo", "ddi_pseudo", "ipmi",
61 TYPE_EXACT
| DRV_EXACT
, ILEVEL_0
, ipmi
,
63 { "pseudo", "ddi_pseudo", "smbios",
64 TYPE_EXACT
| DRV_EXACT
, ILEVEL_1
, smbios
,
66 /* floppies share the same class, but not link regex, as hard disks */
67 { "disk", "ddi_block:diskette", NULL
,
68 TYPE_EXACT
, ILEVEL_1
, diskette
70 { "parallel", "ddi_printer", NULL
,
71 TYPE_EXACT
, ILEVEL_1
, lp
73 { "serial", "ddi_serial:mb", NULL
,
74 TYPE_EXACT
, ILEVEL_1
, serial
76 { "serial", "ddi_serial:dialout,mb", NULL
,
77 TYPE_EXACT
, ILEVEL_1
, serial_dialout
79 { "pseudo", "ddi_pseudo", NULL
,
80 TYPE_EXACT
, ILEVEL_0
, xsvc
82 { "pseudo", "ddi_pseudo", NULL
,
83 TYPE_EXACT
, ILEVEL_0
, srn
85 { "memory-controller", "ddi_mem_ctrl", NULL
,
86 TYPE_EXACT
, ILEVEL_0
, mc_node
88 { "pseudo", "ddi_pseudo", "ucode",
89 TYPE_EXACT
| DRV_EXACT
, ILEVEL_0
, ucode
,
93 DEVFSADM_CREATE_INIT_V0(misc_cbt
);
95 static devfsadm_remove_t misc_remove_cbt
[] = {
96 { "vt", "vt[0-9][0-9]", RM_PRE
|RM_ALWAYS
,
97 ILEVEL_0
, devfsadm_rm_all
99 { "pseudo", "^ucode$", RM_ALWAYS
| RM_PRE
| RM_HOT
,
100 ILEVEL_0
, devfsadm_rm_all
102 { "mouse", "^kdmouse$", RM_ALWAYS
| RM_PRE
,
103 ILEVEL_0
, devfsadm_rm_all
105 { "disk", "^(diskette|rdiskette)([0-9]*)$",
106 RM_ALWAYS
| RM_PRE
, ILEVEL_1
, devfsadm_rm_all
108 { "parallel", "^(lp|ecpp)([0-9]+)$", RM_ALWAYS
| RM_PRE
,
109 ILEVEL_1
, devfsadm_rm_all
111 { "serial", "^(tty|ttyd)([0-9]+)$", RM_ALWAYS
| RM_PRE
,
112 ILEVEL_1
, devfsadm_rm_all
114 { "serial", "^tty[a-z]$", RM_ALWAYS
| RM_PRE
,
115 ILEVEL_1
, devfsadm_rm_all
119 DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt
);
122 * Handles minor node type "ddi_display", in addition to generic processing
125 * This creates a /dev/vt00 link to /dev/fb, for backwards compatibility.
129 vt00(di_minor_t minor
, di_node_t node
)
131 (void) devfsadm_secondary_link("vt00", "fb", 0);
132 return (DEVFSADM_CONTINUE
);
136 * type=ddi_block:diskette;addr=0,0;minor=c diskette
137 * type=ddi_block:diskette;addr=0,0;minor=c,raw rdiskette
138 * type=ddi_block:diskette;addr1=0;minor=c diskette\A2
139 * type=ddi_block:diskette;addr1=0;minor=c,raw rdiskette\A2
142 diskette(di_minor_t minor
, di_node_t node
)
147 char *addr
= di_bus_addr(node
);
148 char *mn
= di_minor_name(minor
);
151 flags
= DA_ADD
|DA_FLOPPY
;
153 if (strcmp(addr
, "0,0") == 0) {
154 if (strcmp(mn
, "c") == 0) {
155 (void) devfsadm_mklink("diskette", node
, minor
, flags
);
156 } else if (strcmp(mn
, "c,raw") == 0) {
157 (void) devfsadm_mklink("rdiskette", node
, minor
, flags
);
162 if (addr
[0] == '0') {
163 if ((a2
= strchr(addr
, ',')) != NULL
) {
165 if (strcmp(mn
, "c") == 0) {
166 (void) strcpy(link
, "diskette");
167 (void) strcat(link
, a2
);
168 (void) devfsadm_mklink(link
, node
, minor
,
170 } else if (strcmp(mn
, "c,raw") == 0) {
171 (void) strcpy(link
, "rdiskette");
172 (void) strcat(link
, a2
);
173 (void) devfsadm_mklink(link
, node
, minor
,
179 return (DEVFSADM_CONTINUE
);
183 * type=ddi_printer;name=lp;addr=1,3bc lp0
184 * type=ddi_printer;name=lp;addr=1,378 lp1
185 * type=ddi_printer;name=lp;addr=1,278 lp2
188 lp(di_minor_t minor
, di_node_t node
)
190 char *addr
= di_bus_addr(node
);
192 char path
[PATH_MAX
+ 1];
193 devfsadm_enumerate_t rules
[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL
};
195 if (strcmp(addr
, "1,3bc") == 0) {
196 (void) devfsadm_mklink("lp0", node
, minor
, 0);
198 } else if (strcmp(addr
, "1,378") == 0) {
199 (void) devfsadm_mklink("lp1", node
, minor
, 0);
201 } else if (strcmp(addr
, "1,278") == 0) {
202 (void) devfsadm_mklink("lp2", node
, minor
, 0);
205 if (strcmp(di_driver_name(node
), "ecpp") != 0) {
206 return (DEVFSADM_CONTINUE
);
209 if ((buf
= di_devfs_path(node
)) == NULL
) {
210 return (DEVFSADM_CONTINUE
);
213 (void) snprintf(path
, sizeof (path
), "%s:%s",
214 buf
, di_minor_name(minor
));
216 di_devfs_path_free(buf
);
218 if (devfsadm_enumerate_int(path
, 0, &buf
, rules
, 1)) {
219 return (DEVFSADM_CONTINUE
);
222 (void) snprintf(path
, sizeof (path
), "ecpp%s", buf
);
224 (void) devfsadm_mklink(path
, node
, minor
, 0);
225 return (DEVFSADM_CONTINUE
);
229 * type=ddi_serial:mb;minor=a tty00
230 * type=ddi_serial:mb;minor=b tty01
231 * type=ddi_serial:mb;minor=c tty02
232 * type=ddi_serial:mb;minor=d tty03
235 serial(di_minor_t minor
, di_node_t node
)
238 char *mn
= di_minor_name(minor
);
241 (void) strcpy(link
, "tty");
242 (void) strcat(link
, mn
);
243 (void) devfsadm_mklink(link
, node
, minor
, 0);
245 if (strcmp(mn
, "a") == 0) {
246 (void) devfsadm_mklink("tty00", node
, minor
, 0);
248 } else if (strcmp(mn
, "b") == 0) {
249 (void) devfsadm_mklink("tty01", node
, minor
, 0);
251 } else if (strcmp(mn
, "c") == 0) {
252 (void) devfsadm_mklink("tty02", node
, minor
, 0);
254 } else if (strcmp(mn
, "d") == 0) {
255 (void) devfsadm_mklink("tty03", node
, minor
, 0);
257 return (DEVFSADM_CONTINUE
);
261 * type=ddi_serial:dialout,mb;minor=a,cu ttyd0
262 * type=ddi_serial:dialout,mb;minor=b,cu ttyd1
263 * type=ddi_serial:dialout,mb;minor=c,cu ttyd2
264 * type=ddi_serial:dialout,mb;minor=d,cu ttyd3
267 serial_dialout(di_minor_t minor
, di_node_t node
)
269 char *mn
= di_minor_name(minor
);
271 if (strcmp(mn
, "a,cu") == 0) {
272 (void) devfsadm_mklink("ttyd0", node
, minor
, 0);
273 (void) devfsadm_mklink("cua0", node
, minor
, 0);
275 } else if (strcmp(mn
, "b,cu") == 0) {
276 (void) devfsadm_mklink("ttyd1", node
, minor
, 0);
277 (void) devfsadm_mklink("cua1", node
, minor
, 0);
279 } else if (strcmp(mn
, "c,cu") == 0) {
280 (void) devfsadm_mklink("ttyd2", node
, minor
, 0);
281 (void) devfsadm_mklink("cua2", node
, minor
, 0);
283 } else if (strcmp(mn
, "d,cu") == 0) {
284 (void) devfsadm_mklink("ttyd3", node
, minor
, 0);
285 (void) devfsadm_mklink("cua3", node
, minor
, 0);
287 return (DEVFSADM_CONTINUE
);
291 kdmouse(di_minor_t minor
, di_node_t node
)
293 (void) devfsadm_mklink("kdmouse", node
, minor
, 0);
294 return (DEVFSADM_CONTINUE
);
298 ipmi(di_minor_t minor
, di_node_t node
)
301 * Follow convention from other systems, and include an instance#,
302 * even though there will only be one.
304 (void) devfsadm_mklink("ipmi0", node
, minor
, 0);
305 return (DEVFSADM_CONTINUE
);
309 smbios(di_minor_t minor
, di_node_t node
)
311 (void) devfsadm_mklink("smbios", node
, minor
, 0);
312 return (DEVFSADM_CONTINUE
);
316 * /dev/mc/mc<chipid> -> /devices/.../pci1022,1102@<chipid+24>,2:mc-amd
319 mc_node(di_minor_t minor
, di_node_t node
)
321 const char *minorname
= di_minor_name(minor
);
322 const char *busaddr
= di_bus_addr(node
);
323 char linkpath
[PATH_MAX
];
327 if (minorname
== NULL
|| busaddr
== NULL
)
328 return (DEVFSADM_CONTINUE
);
331 unitaddr
= strtol(busaddr
, &c
, 16);
334 return (DEVFSADM_CONTINUE
);
337 (void) snprintf(linkpath
, sizeof (linkpath
), "mc/mc");
338 } else if (unitaddr
>= MC_AMD_DEV_OFFSET
) {
339 (void) snprintf(linkpath
, sizeof (linkpath
), "mc/mc%u",
340 unitaddr
- MC_AMD_DEV_OFFSET
);
342 (void) snprintf(linkpath
, sizeof (linkpath
), "mc/mc%u",
345 (void) devfsadm_mklink(linkpath
, node
, minor
, 0);
346 return (DEVFSADM_CONTINUE
);
350 * Creates \M0 devlink for xsvc node
353 xsvc(di_minor_t minor
, di_node_t node
)
357 if (strcmp(di_node_name(node
), "xsvc") != 0)
358 return (DEVFSADM_CONTINUE
);
360 mn
= di_minor_name(minor
);
362 return (DEVFSADM_CONTINUE
);
364 (void) devfsadm_mklink(mn
, node
, minor
, 0);
365 return (DEVFSADM_CONTINUE
);
369 * Creates \M0 devlink for srn device
372 srn(di_minor_t minor
, di_node_t node
)
376 if (strcmp(di_node_name(node
), "srn") != 0)
377 return (DEVFSADM_CONTINUE
);
379 mn
= di_minor_name(minor
);
381 return (DEVFSADM_CONTINUE
);
383 (void) devfsadm_mklink(mn
, node
, minor
, 0);
384 return (DEVFSADM_CONTINUE
);
388 * /dev/ucode -> /devices/pseudo/ucode@0:ucode
391 ucode(di_minor_t minor
, di_node_t node
)
393 (void) devfsadm_mklink("ucode", node
, minor
, 0);
394 return (DEVFSADM_CONTINUE
);