1 /* $NetBSD: devopen.c,v 1.11 2012/12/19 13:53:47 kiyohara Exp $ */
2
3 /*-
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <lib/libsa/stand.h>
32 #include <lib/libkern/libkern.h>
33 #include <sys/param.h>
34 #include <sys/reboot.h>
35
36 static int devparse(const char *, int *, int *, int *, int *, int *, char **);
37
38
39 /*
40 * Parse a device spec.
41 * i.e.
42 * /dev/disk/floppy
43 * /dev/disk/ide/0/master/0_n
44 * /dev/disk/ide/0/slave/0_n
45 * /dev/disk/scsi/000/0_n
46 * /dev/disk/scsi/030/0_n
47 */
48 static int
devparse(const char * fname,int * dev,int * ctlr,int * unit,int * lunit,int * part,char ** file)49 devparse(const char *fname, int *dev, int *ctlr, int *unit, int *lunit,
50 int *part, char **file)
51 {
52 int i;
53 char devdir[] = "/dev/disk/";
54 char floppy[] = "floppy";
55 char ide[] = "ide";
56 char scsi[] = "scsi";
57 char *p;
58
59 if (strncmp(fname, devdir, strlen(devdir)) != 0)
60 return EINVAL;
61 p = __UNCONST(fname) + strlen(devdir);
62
63 if (strncmp(p, floppy, strlen(floppy)) == 0) {
64 p += strlen(floppy);
65 for (i = 0; devsw[i].dv_name != NULL; i++)
66 if (strcmp(devsw[i].dv_name, "fd") == 0) {
67 *dev = i;
68 *ctlr = 0;
69 *unit = 1;
70 *lunit = 0;
71 break;
72 }
73 } else if (strncmp(p, ide, strlen(ide)) == 0) {
74 char master[] = "master";
75 char slave[] = "slave";
76
77 p += strlen(ide);
78 if (*p++ != '/' ||
79 !isdigit(*p++) ||
80 *p++ != '/')
81 return EINVAL;
82 *ctlr = *(p - 2) - '0';
83 if (strncmp(p, master, strlen(master)) == 0) {
84 *unit = 0;
85 p += strlen(master);
86 } else if (strncmp(p, slave, strlen(slave)) == 0) {
87 *unit = 1;
88 p += strlen(slave);
89 } else
90 return EINVAL;
91 if (*p++ != '/' ||
92 !isdigit(*p++) ||
93 *p++ != '_' ||
94 !isdigit(*p++))
95 return EINVAL;
96 *lunit = *(p - 3) - '0';
97 *part = *(p - 1) - '0';
98 for (i = 0; devsw[i].dv_name != NULL; i++)
99 if (strcmp(devsw[i].dv_name, "wd") == 0) {
100 *dev = i;
101 break;
102 }
103 if (devsw[i].dv_name == NULL)
104 return EINVAL;
105 } else if (strncmp(p, scsi, strlen(scsi)) == 0) {
106 p += strlen(scsi);
107 if (*p++ != '/' ||
108 !isdigit(*p++) ||
109 !isdigit(*p++) ||
110 !isdigit(*p++) ||
111 *p++ != '/' ||
112 !isdigit(*p++) ||
113 *p++ != '_' ||
114 !isdigit(*p++))
115 return EINVAL;
116 *ctlr = *(p - 7) - '0';
117 *unit = *(p - 6) - '0';
118 *lunit = *(p - 5) - '0';
119 *part = *(p - 1) - '0';
120 for (i = 0; devsw[i].dv_name != NULL; i++)
121 if (strcmp(devsw[i].dv_name, "sd") == 0) {
122 *dev = i;
123 break;
124 }
125 if (devsw[i].dv_name == NULL)
126 return EINVAL;
127 }
128
129 if (*p++ != ':')
130 return EINVAL;
131 *file = p;
132 return 0;
133 }
134
135 int
devopen(struct open_file * f,const char * fname,char ** file)136 devopen(struct open_file *f, const char *fname, char **file)
137 {
138 int error;
139 int dev = 0, ctlr = 0, unit = 0, lunit = 0, part = 0;
140 struct devsw *dp = &devsw[0];
141 extern struct devsw pseudo_devsw;
142
143 **file = '\0';
144 error = devparse(fname, &dev, &ctlr, &unit, &lunit, &part, file);
145 if (error == 0) {
146 dp = &devsw[dev];
147 if (!dp->dv_open)
148 return ENODEV;
149 } else {
150 if (strcmp(fname, "in") == 0)
151 /* special case: kernel in memory */
152 dp = &pseudo_devsw;
153 else
154 return error;
155 }
156
157 f->f_dev = dp;
158 if ((error = (*dp->dv_open)(f, ctlr, unit, lunit, part)) == 0)
159 return 0;
160
161 printf("%s %s\n", fname, strerror(error));
162
163 return error;
164 }
165