1 /* $NetBSD: devopen.c,v 1.7 2016/06/26 04:17:17 isaki Exp $ */
2
3 /*
4 * Copyright (c) 2001 Minoura Makoto
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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <sys/disklabel.h>
31 #include <machine/bootinfo.h>
32 #include <lib/libkern/libkern.h>
33 #include <lib/libsa/stand.h>
34 #include "libx68k.h"
35
36 extern struct devspec devspec[]; /* defined in conf.c */
37 int devopen_open_dir = 0;
38
39 /*
40 * Parse a device spec.
41 *
42 * [ha@]<dev><unit><part>:<file>
43 * ha - host adaptor ("spc0", "spc1", "mha0")
44 * dev - device name (e.g., "sd")
45 * unit - 0-7
46 * part - a-p
47 */
48 int
devparse(const char * fname,int * ha,int * dev,int * unit,int * part,char ** file)49 devparse(const char *fname, int *ha, int *dev, int *unit, int *part,
50 char **file)
51 {
52 char const *s;
53 int i;
54
55 s = fname;
56
57 if (strncmp(s, "spc0@", 5) == 0) {
58 *ha = (X68K_BOOT_SCSIIF_SPC << 4) | 0;
59 s += 5;
60 } else if (strncmp(s, "spc1@", 5) == 0) {
61 *ha = (X68K_BOOT_SCSIIF_SPC << 4) | 1;
62 s += 5;
63 } else if (strncmp(s, "mha0@", 5) == 0) {
64 *ha = (X68K_BOOT_SCSIIF_MHA << 4) | 0;
65 s += 5;
66 } else {
67 *ha = 0;
68 }
69
70 for (i = 0; devspec[i].ds_name != 0; i++) {
71 if (strncmp (devspec[i].ds_name, s,
72 strlen(devspec[i].ds_name)) == 0)
73 break;
74 }
75
76 if (devspec[i].ds_name == 0)
77 return ENODEV;
78 s += strlen(devspec[i].ds_name);
79 *dev = devspec[i].ds_dev;
80
81 if (devspec[i].ds_net) {
82 *unit = 0;
83 *part = 0;
84 } else {
85 *unit = *s++ - '0';
86 if (*unit < 0 || *unit > devspec[i].ds_maxunit)
87 /* bad unit */
88 return ENODEV;
89 *part = *s++ - 'a';
90 if (*part < 0 || *part > MAXPARTITIONS)
91 /* bad partition */
92 return ENODEV;
93 }
94
95 if (*s++ != ':')
96 return ENODEV;
97
98 if (*s == '/') {
99 s++;
100 if (devopen_open_dir && *s == 0)
101 s--;
102 }
103 *file = __UNCONST(s);
104
105 return 0;
106 }
107
108 int
devopen(struct open_file * f,const char * fname,char ** file)109 devopen(struct open_file *f, const char *fname, char **file)
110 {
111 int error;
112 int ha, dev, unit, part;
113 struct devsw *dp = &devsw[0];
114
115 error = devparse(fname, &ha, &dev, &unit, &part, file);
116 if (error)
117 return error;
118
119 dp = &devsw[dev];
120
121 if (dp->dv_open == NULL)
122 return ENODEV;
123
124 f->f_dev = dp;
125
126 if ((error = (*dp->dv_open)(f, unit, part)) == 0)
127 return 0;
128
129 return error;
130 }
131