xref: /netbsd-src/sys/arch/hp300/stand/common/devopen.c (revision d0fed6c87ddc40a8bffa6f99e7433ddfc864dd83)
1 /*	$NetBSD: devopen.c,v 1.1 1997/02/04 03:52:23 thorpej Exp $	*/
2 
3 /*-
4  *  Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
5  *  Copyright (c) 1993 John Brezak
6  *  All rights reserved.
7  *
8  *  Redistribution and use in source and binary forms, with or without
9  *  modification, are permitted provided that the following conditions
10  *  are met:
11  *  1. Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *  2. Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  *  3. The name of the author may not be used to endorse or promote products
17  *     derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/param.h>
33 #include <sys/reboot.h>
34 
35 #include <lib/libsa/stand.h>
36 #include <hp300/stand/common/samachdep.h>
37 
38 u_int opendev;
39 
40 #define ispart(c)	((c) >= 'a' && (c) <= 'h')
41 
42 atoi(char *cp)
43 {
44     int val = 0;
45     while(isdigit(*cp))
46 	val = val * 10 + (*cp++ - '0');
47     return(val);
48 }
49 
50 usage()
51 {
52     printf("\
53 Usage: device(adaptor, controller, drive, partition)file\n\
54        <device><unit><partitionletter>:file\n\
55 ");
56 }
57 
58 devlookup(d, len)
59 	const char *d;
60 	int len;
61 {
62     struct devsw *dp = devsw;
63     int i;
64 
65     for (i = 0; i < ndevs; i++, dp++) {
66 	if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0) {
67 	    /*
68 	     * Set the filesystem and startup up according to the device
69 	     * being opened.
70 	     */
71 	    switch (i) {
72 	    case 0:	/* ct */
73 		bcopy(file_system_rawfs, file_system, sizeof(struct fs_ops));
74 		break;
75 
76 	    case 2:	/* rd */
77 	    case 4:	/* sd */
78 		bcopy(file_system_ufs, file_system, sizeof(struct fs_ops));
79 		break;
80 
81 	    case 6:	/* le */
82 		bcopy(file_system_nfs, file_system, sizeof(struct fs_ops));
83 		break;
84 
85 	    default:
86 		/* Agh!  What happened?! */
87 		goto bad;
88 	    }
89 	    return(i);
90 	}
91     }
92 
93  bad:
94     printf("No such device - Configured devices are:\n");
95     for (dp = devsw, i = 0; i < ndevs; i++, dp++)
96 	if (dp->dv_name)
97 	    printf(" %s", dp->dv_name);
98     printf("\n");
99     errno = ENODEV;
100     return(-1);
101 }
102 
103 /*
104  * Parse a device spec in one of two forms.
105  *
106  * dev(adapt, ctlr, unit, part)file
107  * [A-Za-z]*[0-9]*[A-Za-z]:file
108  *    dev   unit  part
109  */
110 devparse(fname, dev, adapt, ctlr, unit, part, file)
111 	const char *fname;
112 	int *dev, *adapt, *ctlr, *unit, *part;
113 	char **file;
114 {
115     int *argp, i;
116     char *s, *args[4];
117 
118     /* get device name and make lower case */
119     for (s = (char *)fname; *s && *s != '/' && *s != ':' && *s != '('; s++)
120 	if (isupper(*s)) *s = tolower(*s);
121 
122     /* first form */
123     if (*s == '(') {
124 	/* lookup device and get index */
125 	if ((*dev = devlookup(fname, s - fname)) < 0)
126 	    goto baddev;
127 
128 	/* tokenize device ident */
129 	args[0] = ++s;
130 	for (args[0] = s, i = 1; *s && *s != ')'; s++) {
131 	    if (*s == ',')
132 		args[i++] = ++s;
133 	}
134 	switch(i) {
135 	case 4:
136 	    *adapt = atoi(args[0]);
137 	    *ctlr  = atoi(args[1]);
138 	    *unit  = atoi(args[2]);
139 	    *part  = atoi(args[3]);
140 	    break;
141 	case 3:
142 	    *ctlr  = atoi(args[0]);
143 	    *unit  = atoi(args[1]);
144 	    *part  = atoi(args[2]);
145 	    break;
146 	case 2:
147 	    *unit  = atoi(args[0]);
148 	    *part  = atoi(args[1]);
149 	    break;
150 	case 1:
151 	    *part  = atoi(args[0]);
152 	    break;
153 	case 0:
154 	    break;
155 	}
156 	*file = ++s;
157     }
158 
159     /* second form */
160     else if (*s == ':') {
161 	int temp;
162 
163 	/* isolate device */
164 	for (s = (char *)fname; *s != ':' && !isdigit(*s); s++);
165 
166 	/* lookup device and get index */
167 	if ((*dev = devlookup(fname, s - fname)) < 0)
168 	    goto baddev;
169 
170 	/* isolate unit */
171 	if ((temp = atoi(s)) > 255)
172 	    goto bad;
173 	*adapt = temp / 8;
174 	*ctlr = temp % 8;
175 	for (; isdigit(*s); s++);
176 
177 	/* translate partition */
178 	if (!ispart(*s))
179 	    goto bad;
180 
181 	*part = *s++ - 'a';
182 	if (*s != ':')
183 	    goto bad;
184 	*file = ++s;
185     }
186 
187     /* no device present */
188     else
189 	*file = (char *)fname;
190 
191     /* return the remaining unparsed part as the file to boot */
192     return(0);
193 
194  bad:
195     usage();
196 
197  baddev:
198     return(-1);
199 }
200 
201 
202 devopen(f, fname, file)
203 	struct open_file *f;
204 	const char *fname;
205 	char **file;
206 {
207 	int n, error;
208 	int dev, adapt, ctlr, unit, part;
209 	struct devsw *dp = &devsw[0];
210 
211 	dev   = B_TYPE(bootdev);
212 	adapt = B_ADAPTOR(bootdev);
213 	ctlr  = B_CONTROLLER(bootdev);
214 	unit  = B_UNIT(bootdev);
215 	part  = B_PARTITION(bootdev);
216 
217 	if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file))
218 	    return(error);
219 
220 	/*
221 	 * Set up filesystem type based on what device we're opening.
222 	 */
223 	switch (dev) {
224 	case 0:		/* ct */
225 		bcopy(file_system_rawfs, file_system, sizeof(struct fs_ops));
226 		break;
227 
228 	case 2:		/* rd */
229 	case 4:		/* sd */
230 		bcopy(file_system_ufs, file_system, sizeof(struct fs_ops));
231 		break;
232 
233 	case 6:		/* le */
234 		bcopy(file_system_nfs, file_system, sizeof(struct fs_ops));
235 		break;
236 
237 	default:
238 		/* XXX what else should we do here? */
239 		printf("WARNING: BOGUS BOOT DEV TYPE 0x%x!\n", dev);
240 		return (EIO);
241 	}
242 
243 	dp = &devsw[dev];
244 
245 	if (!dp->dv_open)
246 		return(ENODEV);
247 
248 	f->f_dev = dp;
249 
250 	if ((error = (*dp->dv_open)(f, adapt, ctlr, part)) == 0) {
251 		if ((error =
252 		    (*punitsw[dev].p_punit)(adapt, ctlr, &unit)) != 0) {
253 			goto bad;
254 		}
255 		opendev = MAKEBOOTDEV(dev, adapt, ctlr, unit, part);
256 		return(0);
257 	}
258 
259  bad:
260 	printf("%s(%d,%d,%d,%d): %s\n", devsw[dev].dv_name,
261 	    adapt, ctlr, unit, part, strerror(error));
262 
263 	return(error);
264 }
265