PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/cmd/devfsadm/i386/misc_link_i386.c

https://bitbucket.org/xl0/illumos-next
C | 651 lines | 482 code | 101 blank | 68 comment | 100 complexity | d9af01005f5b18c1aaa348664a5e2bdb MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, GPL-3.0, LGPL-2.1, BSD-2-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.0, AGPL-3.0, BSD-3-Clause, LGPL-3.0, 0BSD
  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 (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  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.
  12. *
  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]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
  23. * Use is subject to license terms.
  24. */
  25. #include <regex.h>
  26. #include <devfsadm.h>
  27. #include <stdio.h>
  28. #include <strings.h>
  29. #include <stdlib.h>
  30. #include <limits.h>
  31. #include <ctype.h>
  32. #include <sys/mc_amd.h>
  33. #include <bsm/devalloc.h>
  34. extern int system_labeled;
  35. static int lp(di_minor_t minor, di_node_t node);
  36. static int serial_dialout(di_minor_t minor, di_node_t node);
  37. static int serial(di_minor_t minor, di_node_t node);
  38. static int diskette(di_minor_t minor, di_node_t node);
  39. static int vt00(di_minor_t minor, di_node_t node);
  40. static int kdmouse(di_minor_t minor, di_node_t node);
  41. static int bmc(di_minor_t minor, di_node_t node);
  42. static int smbios(di_minor_t minor, di_node_t node);
  43. static int agp_process(di_minor_t minor, di_node_t node);
  44. static int drm_node(di_minor_t minor, di_node_t node);
  45. static int mc_node(di_minor_t minor, di_node_t node);
  46. static int xsvc(di_minor_t minor, di_node_t node);
  47. static int srn(di_minor_t minor, di_node_t node);
  48. static int ucode(di_minor_t minor, di_node_t node);
  49. static int heci(di_minor_t minor, di_node_t node);
  50. static devfsadm_create_t misc_cbt[] = {
  51. { "vt00", "ddi_display", NULL,
  52. TYPE_EXACT, ILEVEL_0, vt00
  53. },
  54. { "drm", "ddi_display:drm", NULL,
  55. TYPE_EXACT, ILEVEL_0, drm_node
  56. },
  57. { "mouse", "ddi_mouse", "mouse8042",
  58. TYPE_EXACT | DRV_EXACT, ILEVEL_0, kdmouse
  59. },
  60. { "pseudo", "ddi_pseudo", "bmc",
  61. TYPE_EXACT | DRV_EXACT, ILEVEL_0, bmc,
  62. },
  63. { "pseudo", "ddi_pseudo", "smbios",
  64. TYPE_EXACT | DRV_EXACT, ILEVEL_1, smbios,
  65. },
  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
  69. },
  70. { "parallel", "ddi_printer", NULL,
  71. TYPE_EXACT, ILEVEL_1, lp
  72. },
  73. { "serial", "ddi_serial:mb", NULL,
  74. TYPE_EXACT, ILEVEL_1, serial
  75. },
  76. { "serial", "ddi_serial:dialout,mb", NULL,
  77. TYPE_EXACT, ILEVEL_1, serial_dialout
  78. },
  79. { "agp", "ddi_agp:pseudo", NULL,
  80. TYPE_EXACT, ILEVEL_0, agp_process
  81. },
  82. { "agp", "ddi_agp:target", NULL,
  83. TYPE_EXACT, ILEVEL_0, agp_process
  84. },
  85. { "agp", "ddi_agp:cpugart", NULL,
  86. TYPE_EXACT, ILEVEL_0, agp_process
  87. },
  88. { "agp", "ddi_agp:master", NULL,
  89. TYPE_EXACT, ILEVEL_0, agp_process
  90. },
  91. { "pseudo", "ddi_pseudo", NULL,
  92. TYPE_EXACT, ILEVEL_0, xsvc
  93. },
  94. { "pseudo", "ddi_pseudo", NULL,
  95. TYPE_EXACT, ILEVEL_0, srn
  96. },
  97. { "memory-controller", "ddi_mem_ctrl", NULL,
  98. TYPE_EXACT, ILEVEL_0, mc_node
  99. },
  100. { "pseudo", "ddi_pseudo", "ucode",
  101. TYPE_EXACT | DRV_EXACT, ILEVEL_0, ucode,
  102. },
  103. { "pseudo", "ddi_pseudo", "heci",
  104. TYPE_EXACT | DRV_EXACT, ILEVEL_0, heci,
  105. }
  106. };
  107. DEVFSADM_CREATE_INIT_V0(misc_cbt);
  108. static char *debug_mid = "misc_mid";
  109. typedef enum {
  110. DRIVER_AGPPSEUDO = 0,
  111. DRIVER_AGPTARGET,
  112. DRIVER_CPUGART,
  113. DRIVER_AGPMASTER_DRM_I915,
  114. DRIVER_AGPMASTER_DRM_RADEON,
  115. DRIVER_AGPMASTER_VGATEXT,
  116. DRIVER_UNKNOWN
  117. } driver_defs_t;
  118. typedef struct {
  119. char *driver_name;
  120. int index;
  121. } driver_name_table_entry_t;
  122. static driver_name_table_entry_t driver_name_table[] = {
  123. { "agpgart", DRIVER_AGPPSEUDO },
  124. { "agptarget", DRIVER_AGPTARGET },
  125. { "amd64_gart", DRIVER_CPUGART },
  126. /* AGP master device managed by drm driver */
  127. { "i915", DRIVER_AGPMASTER_DRM_I915 },
  128. { "radeon", DRIVER_AGPMASTER_DRM_RADEON },
  129. { "vgatext", DRIVER_AGPMASTER_VGATEXT },
  130. { NULL, DRIVER_UNKNOWN }
  131. };
  132. static devfsadm_enumerate_t agptarget_rules[1] =
  133. { "^agp$/^agptarget([0-9]+)$", 1, MATCH_ALL };
  134. static devfsadm_enumerate_t cpugart_rules[1] =
  135. { "^agp$/^cpugart([0-9]+)$", 1, MATCH_ALL };
  136. static devfsadm_enumerate_t agpmaster_rules[1] =
  137. { "^agp$/^agpmaster([0-9]+)$", 1, MATCH_ALL };
  138. static devfsadm_remove_t misc_remove_cbt[] = {
  139. { "vt", "vt[0-9][0-9]", RM_PRE|RM_ALWAYS,
  140. ILEVEL_0, devfsadm_rm_all
  141. },
  142. { "pseudo", "^ucode$", RM_ALWAYS | RM_PRE | RM_HOT,
  143. ILEVEL_0, devfsadm_rm_all
  144. },
  145. { "mouse", "^kdmouse$", RM_ALWAYS | RM_PRE,
  146. ILEVEL_0, devfsadm_rm_all
  147. },
  148. { "disk", "^(diskette|rdiskette)([0-9]*)$",
  149. RM_ALWAYS | RM_PRE, ILEVEL_1, devfsadm_rm_all
  150. },
  151. { "parallel", "^(lp|ecpp)([0-9]+)$", RM_ALWAYS | RM_PRE,
  152. ILEVEL_1, devfsadm_rm_all
  153. },
  154. { "serial", "^(tty|ttyd)([0-9]+)$", RM_ALWAYS | RM_PRE,
  155. ILEVEL_1, devfsadm_rm_all
  156. },
  157. { "serial", "^tty[a-z]$", RM_ALWAYS | RM_PRE,
  158. ILEVEL_1, devfsadm_rm_all
  159. }
  160. };
  161. DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt);
  162. /*
  163. * Handles minor node type "ddi_display", in addition to generic processing
  164. * done by display().
  165. *
  166. * This creates a /dev/vt00 link to /dev/fb, for backwards compatibility.
  167. */
  168. /* ARGSUSED */
  169. int
  170. vt00(di_minor_t minor, di_node_t node)
  171. {
  172. (void) devfsadm_secondary_link("vt00", "fb", 0);
  173. return (DEVFSADM_CONTINUE);
  174. }
  175. /*
  176. * type=ddi_block:diskette;addr=0,0;minor=c diskette
  177. * type=ddi_block:diskette;addr=0,0;minor=c,raw rdiskette
  178. * type=ddi_block:diskette;addr1=0;minor=c diskette\A2
  179. * type=ddi_block:diskette;addr1=0;minor=c,raw rdiskette\A2
  180. */
  181. static int
  182. diskette(di_minor_t minor, di_node_t node)
  183. {
  184. int flags = 0;
  185. char *a2;
  186. char link[PATH_MAX];
  187. char *addr = di_bus_addr(node);
  188. char *mn = di_minor_name(minor);
  189. if (system_labeled)
  190. flags = DA_ADD|DA_FLOPPY;
  191. if (strcmp(addr, "0,0") == 0) {
  192. if (strcmp(mn, "c") == 0) {
  193. (void) devfsadm_mklink("diskette", node, minor, flags);
  194. } else if (strcmp(mn, "c,raw") == 0) {
  195. (void) devfsadm_mklink("rdiskette", node, minor, flags);
  196. }
  197. }
  198. if (addr[0] == '0') {
  199. if ((a2 = strchr(addr, ',')) != NULL) {
  200. a2++;
  201. if (strcmp(mn, "c") == 0) {
  202. (void) strcpy(link, "diskette");
  203. (void) strcat(link, a2);
  204. (void) devfsadm_mklink(link, node, minor,
  205. flags);
  206. } else if (strcmp(mn, "c,raw") == 0) {
  207. (void) strcpy(link, "rdiskette");
  208. (void) strcat(link, a2);
  209. (void) devfsadm_mklink(link, node, minor,
  210. flags);
  211. }
  212. }
  213. }
  214. return (DEVFSADM_CONTINUE);
  215. }
  216. /*
  217. * type=ddi_printer;name=lp;addr=1,3bc lp0
  218. * type=ddi_printer;name=lp;addr=1,378 lp1
  219. * type=ddi_printer;name=lp;addr=1,278 lp2
  220. */
  221. static int
  222. lp(di_minor_t minor, di_node_t node)
  223. {
  224. char *addr = di_bus_addr(node);
  225. char *buf;
  226. char path[PATH_MAX + 1];
  227. devfsadm_enumerate_t rules[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL};
  228. if (strcmp(addr, "1,3bc") == 0) {
  229. (void) devfsadm_mklink("lp0", node, minor, 0);
  230. } else if (strcmp(addr, "1,378") == 0) {
  231. (void) devfsadm_mklink("lp1", node, minor, 0);
  232. } else if (strcmp(addr, "1,278") == 0) {
  233. (void) devfsadm_mklink("lp2", node, minor, 0);
  234. }
  235. if (strcmp(di_driver_name(node), "ecpp") != 0) {
  236. return (DEVFSADM_CONTINUE);
  237. }
  238. if ((buf = di_devfs_path(node)) == NULL) {
  239. return (DEVFSADM_CONTINUE);
  240. }
  241. (void) snprintf(path, sizeof (path), "%s:%s",
  242. buf, di_minor_name(minor));
  243. di_devfs_path_free(buf);
  244. if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
  245. return (DEVFSADM_CONTINUE);
  246. }
  247. (void) snprintf(path, sizeof (path), "ecpp%s", buf);
  248. free(buf);
  249. (void) devfsadm_mklink(path, node, minor, 0);
  250. return (DEVFSADM_CONTINUE);
  251. }
  252. /*
  253. * type=ddi_serial:mb;minor=a tty00
  254. * type=ddi_serial:mb;minor=b tty01
  255. * type=ddi_serial:mb;minor=c tty02
  256. * type=ddi_serial:mb;minor=d tty03
  257. */
  258. static int
  259. serial(di_minor_t minor, di_node_t node)
  260. {
  261. char *mn = di_minor_name(minor);
  262. char link[PATH_MAX];
  263. (void) strcpy(link, "tty");
  264. (void) strcat(link, mn);
  265. (void) devfsadm_mklink(link, node, minor, 0);
  266. if (strcmp(mn, "a") == 0) {
  267. (void) devfsadm_mklink("tty00", node, minor, 0);
  268. } else if (strcmp(mn, "b") == 0) {
  269. (void) devfsadm_mklink("tty01", node, minor, 0);
  270. } else if (strcmp(mn, "c") == 0) {
  271. (void) devfsadm_mklink("tty02", node, minor, 0);
  272. } else if (strcmp(mn, "d") == 0) {
  273. (void) devfsadm_mklink("tty03", node, minor, 0);
  274. }
  275. return (DEVFSADM_CONTINUE);
  276. }
  277. /*
  278. * type=ddi_serial:dialout,mb;minor=a,cu ttyd0
  279. * type=ddi_serial:dialout,mb;minor=b,cu ttyd1
  280. * type=ddi_serial:dialout,mb;minor=c,cu ttyd2
  281. * type=ddi_serial:dialout,mb;minor=d,cu ttyd3
  282. */
  283. static int
  284. serial_dialout(di_minor_t minor, di_node_t node)
  285. {
  286. char *mn = di_minor_name(minor);
  287. if (strcmp(mn, "a,cu") == 0) {
  288. (void) devfsadm_mklink("ttyd0", node, minor, 0);
  289. (void) devfsadm_mklink("cua0", node, minor, 0);
  290. } else if (strcmp(mn, "b,cu") == 0) {
  291. (void) devfsadm_mklink("ttyd1", node, minor, 0);
  292. (void) devfsadm_mklink("cua1", node, minor, 0);
  293. } else if (strcmp(mn, "c,cu") == 0) {
  294. (void) devfsadm_mklink("ttyd2", node, minor, 0);
  295. (void) devfsadm_mklink("cua2", node, minor, 0);
  296. } else if (strcmp(mn, "d,cu") == 0) {
  297. (void) devfsadm_mklink("ttyd3", node, minor, 0);
  298. (void) devfsadm_mklink("cua3", node, minor, 0);
  299. }
  300. return (DEVFSADM_CONTINUE);
  301. }
  302. static int
  303. kdmouse(di_minor_t minor, di_node_t node)
  304. {
  305. (void) devfsadm_mklink("kdmouse", node, minor, 0);
  306. return (DEVFSADM_CONTINUE);
  307. }
  308. static int
  309. bmc(di_minor_t minor, di_node_t node)
  310. {
  311. (void) devfsadm_mklink("bmc", node, minor, 0);
  312. return (DEVFSADM_CONTINUE);
  313. }
  314. static int
  315. smbios(di_minor_t minor, di_node_t node)
  316. {
  317. (void) devfsadm_mklink("smbios", node, minor, 0);
  318. return (DEVFSADM_CONTINUE);
  319. }
  320. static int
  321. agp_process(di_minor_t minor, di_node_t node)
  322. {
  323. char *minor_nm, *drv_nm;
  324. char *devfspath;
  325. char *I_path, *p_path, *buf;
  326. char *name = (char *)NULL;
  327. int i, index;
  328. devfsadm_enumerate_t rules[1];
  329. minor_nm = di_minor_name(minor);
  330. drv_nm = di_driver_name(node);
  331. if ((minor_nm == NULL) || (drv_nm == NULL)) {
  332. return (DEVFSADM_CONTINUE);
  333. }
  334. devfsadm_print(debug_mid, "agp_process: minor=%s node=%s\n",
  335. minor_nm, di_node_name(node));
  336. devfspath = di_devfs_path(node);
  337. if (devfspath == NULL) {
  338. devfsadm_print(debug_mid, "agp_process: devfspath is NULL\n");
  339. return (DEVFSADM_CONTINUE);
  340. }
  341. I_path = (char *)malloc(PATH_MAX);
  342. if (I_path == NULL) {
  343. di_devfs_path_free(devfspath);
  344. devfsadm_print(debug_mid, "agp_process: malloc failed\n");
  345. return (DEVFSADM_CONTINUE);
  346. }
  347. p_path = (char *)malloc(PATH_MAX);
  348. if (p_path == NULL) {
  349. devfsadm_print(debug_mid, "agp_process: malloc failed\n");
  350. di_devfs_path_free(devfspath);
  351. free(I_path);
  352. return (DEVFSADM_CONTINUE);
  353. }
  354. (void) strlcpy(p_path, devfspath, PATH_MAX);
  355. (void) strlcat(p_path, ":", PATH_MAX);
  356. (void) strlcat(p_path, minor_nm, PATH_MAX);
  357. di_devfs_path_free(devfspath);
  358. devfsadm_print(debug_mid, "agp_process: path %s\n", p_path);
  359. for (i = 0; ; i++) {
  360. if ((driver_name_table[i].driver_name == NULL) ||
  361. (strcmp(drv_nm, driver_name_table[i].driver_name) == 0)) {
  362. index = driver_name_table[i].index;
  363. break;
  364. }
  365. }
  366. switch (index) {
  367. case DRIVER_AGPPSEUDO:
  368. devfsadm_print(debug_mid,
  369. "agp_process: psdeudo driver name\n");
  370. name = "agpgart";
  371. (void) snprintf(I_path, PATH_MAX, "%s", name);
  372. devfsadm_print(debug_mid,
  373. "mklink %s -> %s\n", I_path, p_path);
  374. (void) devfsadm_mklink(I_path, node, minor, 0);
  375. free(I_path);
  376. free(p_path);
  377. return (DEVFSADM_CONTINUE);
  378. case DRIVER_AGPTARGET:
  379. devfsadm_print(debug_mid,
  380. "agp_process: target driver name\n");
  381. rules[0] = agptarget_rules[0];
  382. name = "agptarget";
  383. break;
  384. case DRIVER_CPUGART:
  385. devfsadm_print(debug_mid,
  386. "agp_process: cpugart driver name\n");
  387. rules[0] = cpugart_rules[0];
  388. name = "cpugart";
  389. break;
  390. case DRIVER_AGPMASTER_DRM_I915:
  391. case DRIVER_AGPMASTER_DRM_RADEON:
  392. case DRIVER_AGPMASTER_VGATEXT:
  393. devfsadm_print(debug_mid,
  394. "agp_process: agpmaster driver name\n");
  395. rules[0] = agpmaster_rules[0];
  396. name = "agpmaster";
  397. break;
  398. case DRIVER_UNKNOWN:
  399. devfsadm_print(debug_mid,
  400. "agp_process: unknown driver name=%s\n", drv_nm);
  401. free(I_path);
  402. free(p_path);
  403. return (DEVFSADM_CONTINUE);
  404. }
  405. if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
  406. devfsadm_print(debug_mid, "agp_process: exit/coninue\n");
  407. free(I_path);
  408. free(p_path);
  409. return (DEVFSADM_CONTINUE);
  410. }
  411. (void) snprintf(I_path, PATH_MAX, "agp/%s%s", name, buf);
  412. devfsadm_print(debug_mid, "agp_process: p_path=%s buf=%s\n",
  413. p_path, buf);
  414. free(buf);
  415. devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
  416. (void) devfsadm_mklink(I_path, node, minor, 0);
  417. free(p_path);
  418. free(I_path);
  419. return (DEVFSADM_CONTINUE);
  420. }
  421. static int
  422. drm_node(di_minor_t minor, di_node_t node)
  423. {
  424. char *minor_nm, *drv_nm;
  425. char *devfspath;
  426. char *I_path, *p_path, *buf;
  427. char *name = "card";
  428. devfsadm_enumerate_t drm_rules[1] = {"^dri$/^card([0-9]+)$", 1,
  429. MATCH_ALL };
  430. minor_nm = di_minor_name(minor);
  431. drv_nm = di_driver_name(node);
  432. if ((minor_nm == NULL) || (drv_nm == NULL)) {
  433. return (DEVFSADM_CONTINUE);
  434. }
  435. devfsadm_print(debug_mid, "drm_node: minor=%s node=%s type=%s\n",
  436. minor_nm, di_node_name(node), di_minor_nodetype(minor));
  437. devfspath = di_devfs_path(node);
  438. if (devfspath == NULL) {
  439. devfsadm_print(debug_mid, "drm_node: devfspath is NULL\n");
  440. return (DEVFSADM_CONTINUE);
  441. }
  442. I_path = (char *)malloc(PATH_MAX);
  443. if (I_path == NULL) {
  444. di_devfs_path_free(devfspath);
  445. devfsadm_print(debug_mid, "drm_node: malloc failed\n");
  446. return (DEVFSADM_CONTINUE);
  447. }
  448. p_path = (char *)malloc(PATH_MAX);
  449. if (p_path == NULL) {
  450. devfsadm_print(debug_mid, "drm_node: malloc failed\n");
  451. di_devfs_path_free(devfspath);
  452. free(I_path);
  453. return (DEVFSADM_CONTINUE);
  454. }
  455. (void) strlcpy(p_path, devfspath, PATH_MAX);
  456. (void) strlcat(p_path, ":", PATH_MAX);
  457. (void) strlcat(p_path, minor_nm, PATH_MAX);
  458. di_devfs_path_free(devfspath);
  459. devfsadm_print(debug_mid, "drm_node: p_path %s\n", p_path);
  460. if (devfsadm_enumerate_int(p_path, 0, &buf, drm_rules, 1)) {
  461. free(p_path);
  462. devfsadm_print(debug_mid, "drm_node: exit/coninue\n");
  463. return (DEVFSADM_CONTINUE);
  464. }
  465. (void) snprintf(I_path, PATH_MAX, "dri/%s%s", name, buf);
  466. devfsadm_print(debug_mid, "drm_node: p_path=%s buf=%s\n",
  467. p_path, buf);
  468. free(buf);
  469. devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
  470. (void) devfsadm_mklink(I_path, node, minor, 0);
  471. free(p_path);
  472. free(I_path);
  473. return (0);
  474. }
  475. /*
  476. * /dev/mc/mc<chipid> -> /devices/.../pci1022,1102@<chipid+24>,2:mc-amd
  477. */
  478. static int
  479. mc_node(di_minor_t minor, di_node_t node)
  480. {
  481. const char *minorname = di_minor_name(minor);
  482. const char *busaddr = di_bus_addr(node);
  483. char linkpath[PATH_MAX];
  484. int unitaddr;
  485. char *c;
  486. if (minorname == NULL || busaddr == NULL)
  487. return (DEVFSADM_CONTINUE);
  488. errno = 0;
  489. unitaddr = strtol(busaddr, &c, 16);
  490. if (errno != 0)
  491. return (DEVFSADM_CONTINUE);
  492. if (unitaddr == 0) {
  493. (void) snprintf(linkpath, sizeof (linkpath), "mc/mc");
  494. } else if (unitaddr >= MC_AMD_DEV_OFFSET) {
  495. (void) snprintf(linkpath, sizeof (linkpath), "mc/mc%u",
  496. unitaddr - MC_AMD_DEV_OFFSET);
  497. } else {
  498. (void) snprintf(linkpath, sizeof (linkpath), "mc/mc%u",
  499. minor->dev_minor);
  500. }
  501. (void) devfsadm_mklink(linkpath, node, minor, 0);
  502. return (DEVFSADM_CONTINUE);
  503. }
  504. /*
  505. * Creates \M0 devlink for xsvc node
  506. */
  507. static int
  508. xsvc(di_minor_t minor, di_node_t node)
  509. {
  510. char *mn;
  511. if (strcmp(di_node_name(node), "xsvc") != 0)
  512. return (DEVFSADM_CONTINUE);
  513. mn = di_minor_name(minor);
  514. if (mn == NULL)
  515. return (DEVFSADM_CONTINUE);
  516. (void) devfsadm_mklink(mn, node, minor, 0);
  517. return (DEVFSADM_CONTINUE);
  518. }
  519. /*
  520. * Creates \M0 devlink for srn device
  521. */
  522. static int
  523. srn(di_minor_t minor, di_node_t node)
  524. {
  525. char *mn;
  526. if (strcmp(di_node_name(node), "srn") != 0)
  527. return (DEVFSADM_CONTINUE);
  528. mn = di_minor_name(minor);
  529. if (mn == NULL)
  530. return (DEVFSADM_CONTINUE);
  531. (void) devfsadm_mklink(mn, node, minor, 0);
  532. return (DEVFSADM_CONTINUE);
  533. }
  534. /*
  535. * /dev/ucode -> /devices/pseudo/ucode@0:ucode
  536. */
  537. static int
  538. ucode(di_minor_t minor, di_node_t node)
  539. {
  540. (void) devfsadm_mklink("ucode", node, minor, 0);
  541. return (DEVFSADM_CONTINUE);
  542. }
  543. static int
  544. heci(di_minor_t minor, di_node_t node)
  545. {
  546. if (strcmp(di_minor_name(minor), "AMT") == 0) {
  547. (void) devfsadm_mklink("heci", node, minor, 0);
  548. }
  549. return (DEVFSADM_CONTINUE);
  550. }