more stack for boot
[minix.git] / servers / vfs / dmap.c
blob39eca07ca83e02b7b330c491cf408898d5e791ab
1 /* This file contains the table with device <-> driver mappings. It also
2 * contains some routines to dynamically add and/ or remove device drivers
3 * or change mappings.
4 */
6 #include "fs.h"
7 #include "fproc.h"
8 #include <string.h>
9 #include <stdlib.h>
10 #include <ctype.h>
11 #include <unistd.h>
12 #include <minix/com.h>
13 #include <minix/ds.h>
14 #include "param.h"
16 /* Some devices may or may not be there in the next table. */
17 #define DT(enable, opcl, io, driver, flags, label) \
18 { (enable?(opcl):no_dev), (enable?(io):0), \
19 (enable?(driver):0), (flags), label, FALSE },
20 #define NC(x) (NR_CTRLRS >= (x))
22 /* The order of the entries here determines the mapping between major device
23 * numbers and tasks. The first entry (major device 0) is not used. The
24 * next entry is major device 1, etc. Character and block devices can be
25 * intermixed at random. The ordering determines the device numbers in /dev/.
26 * Note that FS knows the device number of /dev/ram/ to load the RAM disk.
27 * Also note that the major device numbers used in /dev/ are NOT the same as
28 * the process numbers of the device drivers.
31 Driver enabled Open/Cls I/O Driver # Flags Device File
32 -------------- -------- ------ ----------- ----- ------ ----
34 struct dmap dmap[NR_DEVICES]; /* actual map */
35 PRIVATE struct dmap init_dmap[] = {
36 DT(1, no_dev, 0, 0, 0, "") /* 0 = not used */
37 DT(1, gen_opcl, gen_io, MEM_PROC_NR, 0, "memory") /* 1 = /dev/mem */
38 DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /* 2 = /dev/fd0 */
39 DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /* 3 = /dev/c0 */
40 DT(1, tty_opcl, gen_io, TTY_PROC_NR, 0, "") /* 4 = /dev/tty00 */
41 DT(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0, "") /* 5 = /dev/tty */
42 DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /* 6 = /dev/lp */
44 #if (MACHINE == IBM_PC)
45 DT(1, no_dev, 0, 0, DMAP_MUTABLE, "") /* 7 = /dev/ip */
46 DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /* 8 = /dev/c1 */
47 DT(0, 0, 0, 0, DMAP_MUTABLE, "") /* 9 = not used */
48 DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /*10 = /dev/c2 */
49 DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /*11 = /dev/filter*/
50 DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*12 = /dev/c3 */
51 DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*13 = /dev/audio */
52 DT(0, 0, 0, 0, DMAP_MUTABLE, "") /*14 = not used */
53 DT(1, gen_opcl, gen_io, LOG_PROC_NR, 0, "") /*15 = /dev/klog */
54 DT(0, no_dev, 0, NONE, DMAP_MUTABLE, "") /*16 = /dev/random*/
55 DT(0, no_dev, 0, 0, DMAP_MUTABLE, "") /*17 = /dev/hello */
56 DT(0, 0, 0, 0, DMAP_MUTABLE, "") /*18 = not used */
57 #endif /* IBM_PC */
60 /*===========================================================================*
61 * do_mapdriver *
62 *===========================================================================*/
63 PUBLIC int do_mapdriver()
65 int r, force, major, proc_nr_n;
66 unsigned long tasknr;
67 vir_bytes label_vir;
68 size_t label_len;
69 char label[LABEL_MAX];
71 if (!super_user)
73 printf("FS: unauthorized call of do_mapdriver by proc %d\n",
74 who_e);
75 return(EPERM); /* only su (should be only RS or some drivers)
76 * may call do_mapdriver.
80 /* Get the label */
81 label_vir= (vir_bytes)m_in.md_label;
82 label_len= m_in.md_label_len;
84 if (label_len+1 > sizeof(label))
86 printf("vfs:do_mapdriver: label too long\n");
87 return EINVAL;
90 r= sys_vircopy(who_e, D, label_vir, SELF, D, (vir_bytes)label,
91 label_len);
92 if (r != OK)
94 printf("vfs:do_mapdriver: sys_vircopy failed: %d\n", r);
95 return EINVAL;
98 label[label_len]= '\0';
100 r= ds_retrieve_label_num(label, &tasknr);
101 if (r != OK)
103 printf("vfs:do_mapdriver: ds doesn't know '%s'\n", label);
104 return EINVAL;
107 if (isokendpt(tasknr, &proc_nr_n) != OK)
109 printf("vfs:do_mapdriver: bad endpoint %d\n", tasknr);
110 return(EINVAL);
113 /* Try to update device mapping. */
114 major= m_in.md_major;
115 force= m_in.md_force;
116 r= map_driver(label, major, tasknr, m_in.md_style, force);
117 if (r == OK)
119 /* If a driver has completed its exec(), it can be announced
120 * to be up.
122 if(force || fproc[proc_nr_n].fp_execced) {
123 dev_up(major);
124 } else {
125 dmap[major].dmap_flags |= DMAP_BABY;
129 return(r);
132 /*===========================================================================*
133 * map_driver *
134 *===========================================================================*/
135 PUBLIC int map_driver(label, major, proc_nr_e, style, force)
136 char *label; /* name of the driver */
137 int major; /* major number of the device */
138 endpoint_t proc_nr_e; /* process number of the driver */
139 int style; /* style of the device */
140 int force;
142 /* Set a new device driver mapping in the dmap table. Given that correct
143 * arguments are given, this only works if the entry is mutable and the
144 * current driver is not busy. If the proc_nr is set to NONE, we're supposed
145 * to unmap it.
147 * Normal error codes are returned so that this function can be used from
148 * a system call that tries to dynamically install a new driver.
150 int proc_nr_n;
151 size_t len;
152 struct dmap *dp;
154 /* Get pointer to device entry in the dmap table. */
155 if (major < 0 || major >= NR_DEVICES) return(ENODEV);
156 dp = &dmap[major];
158 /* Check if we're supposed to unmap it. If so, do it even
159 * if busy or unmutable, as unmap is called when driver has
160 * exited.
162 if(proc_nr_e == NONE) {
163 dp->dmap_opcl = no_dev;
164 dp->dmap_io = no_dev_io;
165 dp->dmap_driver = NONE;
166 dp->dmap_flags = DMAP_MUTABLE; /* When gone, not busy or reserved. */
167 return(OK);
170 /* See if updating the entry is allowed. */
171 if (! (dp->dmap_flags & DMAP_MUTABLE)) return(EPERM);
172 if (dp->dmap_flags & DMAP_BUSY) return(EBUSY);
174 if (!force)
176 /* Check process number of new driver. */
177 if (isokendpt(proc_nr_e, &proc_nr_n) != OK)
178 return(EINVAL);
181 if (label != NULL) {
182 len= strlen(label);
183 if (len+1 > sizeof(dp->dmap_label))
184 panic("map_driver: label too long: %d", len);
185 strcpy(dp->dmap_label, label);
188 /* Try to update the entry. */
189 switch (style) {
190 case STYLE_DEV: dp->dmap_opcl = gen_opcl; break;
191 case STYLE_TTY: dp->dmap_opcl = tty_opcl; break;
192 case STYLE_CLONE: dp->dmap_opcl = clone_opcl; break;
193 default: return(EINVAL);
195 dp->dmap_io = gen_io;
196 dp->dmap_driver = proc_nr_e;
198 if (dp->dmap_async_driver)
199 dp->dmap_io= asyn_io;
201 return(OK);
204 /*===========================================================================*
205 * dmap_unmap_by_endpt *
206 *===========================================================================*/
207 PUBLIC void dmap_unmap_by_endpt(int proc_nr_e)
209 int i, r;
210 for (i=0; i<NR_DEVICES; i++)
211 if(dmap[i].dmap_driver && dmap[i].dmap_driver == proc_nr_e)
212 if((r=map_driver(NULL, i, NONE, 0, 0)) != OK)
213 printf("FS: unmap of p %d / d %d failed: %d\n", proc_nr_e,i,r);
215 return;
219 /*===========================================================================*
220 * build_dmap *
221 *===========================================================================*/
222 PUBLIC void build_dmap()
224 /* Initialize the table with all device <-> driver mappings. Then, map
225 * the boot driver to a controller and update the dmap table to that
226 * selection. The boot driver and the controller it handles are set at
227 * the boot monitor.
229 int i;
230 struct dmap *dp;
232 /* Build table with device <-> driver mappings. */
233 for (i=0; i<NR_DEVICES; i++) {
234 dp = &dmap[i];
235 if (i < sizeof(init_dmap)/sizeof(struct dmap) &&
236 init_dmap[i].dmap_opcl != no_dev) { /* a preset driver */
237 dp->dmap_opcl = init_dmap[i].dmap_opcl;
238 dp->dmap_io = init_dmap[i].dmap_io;
239 dp->dmap_driver = init_dmap[i].dmap_driver;
240 dp->dmap_flags = init_dmap[i].dmap_flags;
241 strcpy(dp->dmap_label, init_dmap[i].dmap_label);
242 dp->dmap_async_driver= FALSE;
243 } else { /* no default */
244 dp->dmap_opcl = no_dev;
245 dp->dmap_io = no_dev_io;
246 dp->dmap_driver = NONE;
247 dp->dmap_flags = DMAP_MUTABLE;
251 dmap[13].dmap_async_driver= TRUE; /* Audio */
252 dmap[15].dmap_async_driver= TRUE; /* Log */
253 dmap[15].dmap_io= asyn_io;
254 dmap[16].dmap_async_driver= TRUE; /* Random */
258 /*===========================================================================*
259 * dmap_driver_match *
260 *===========================================================================*/
261 PUBLIC int dmap_driver_match(endpoint_t proc, int major)
263 if (major < 0 || major >= NR_DEVICES) return(0);
264 if(dmap[major].dmap_driver != NONE && dmap[major].dmap_driver == proc)
265 return 1;
266 return 0;
269 /*===========================================================================*
270 * dmap_endpt_up *
271 *===========================================================================*/
272 PUBLIC void dmap_endpt_up(int proc_e)
274 int i;
275 for (i=0; i<NR_DEVICES; i++) {
276 if(dmap[i].dmap_driver != NONE
277 && dmap[i].dmap_driver == proc_e
278 && (dmap[i].dmap_flags & DMAP_BABY)) {
279 dmap[i].dmap_flags &= ~DMAP_BABY;
280 dev_up(i);
283 return;