minix/servers/fs/dmap.c
Philip Homburg e9aabcf2f8 Disabled building rescue driver (no longer needed). Moved allocmem from
library to the memory driver. Always put output from within TTY directly on
the console. Removed second include of driver.h from tty.c. Made tty_inrepcode
bigger. First step to move PM and FS calls that are not regular (API)
system calls out of callnr.h (renumbered them, and removed them from the
table.c files). Imported the Minix-vmd uname implementation. This provides
a more stable ABI than the current implementation. Added a bit of security
checking. Unfortunately not nearly enough to get a secure system. Fixed a
bug related to the sizes of the programs in the image (in PM patch_mem_chunks).
2006-05-19 12:19:37 +00:00

279 lines
9.3 KiB
C

/* This file contains the table with device <-> driver mappings. It also
* contains some routines to dynamically add and/ or remove device drivers
* or change mappings.
*/
#include "fs.h"
#include "fproc.h"
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <minix/com.h>
#include "param.h"
/* Some devices may or may not be there in the next table. */
#define DT(enable, opcl, io, driver, flags) \
{ (enable?(opcl):no_dev), (enable?(io):0), \
(enable?(driver):0), (flags) },
#define NC(x) (NR_CTRLRS >= (x))
/* The order of the entries here determines the mapping between major device
* numbers and tasks. The first entry (major device 0) is not used. The
* next entry is major device 1, etc. Character and block devices can be
* intermixed at random. The ordering determines the device numbers in /dev/.
* Note that FS knows the device number of /dev/ram/ to load the RAM disk.
* Also note that the major device numbers used in /dev/ are NOT the same as
* the process numbers of the device drivers.
*/
/*
Driver enabled Open/Cls I/O Driver # Flags Device File
-------------- -------- ------ ----------- ----- ------ ----
*/
struct dmap dmap[NR_DEVICES]; /* actual map */
PRIVATE struct dmap init_dmap[] = {
DT(1, no_dev, 0, 0, 0) /* 0 = not used */
DT(1, gen_opcl, gen_io, MEM_PROC_NR, 0) /* 1 = /dev/mem */
DT(0, no_dev, 0, 0, DMAP_MUTABLE) /* 2 = /dev/fd0 */
DT(0, no_dev, 0, 0, DMAP_MUTABLE) /* 3 = /dev/c0 */
DT(1, tty_opcl, gen_io, TTY_PROC_NR, 0) /* 4 = /dev/tty00 */
DT(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0) /* 5 = /dev/tty */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /* 6 = /dev/lp */
#if (MACHINE == IBM_PC)
DT(1, no_dev, 0, 0, DMAP_MUTABLE) /* 7 = /dev/ip */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /* 8 = /dev/c1 */
DT(0, 0, 0, 0, DMAP_MUTABLE) /* 9 = not used */
DT(0, no_dev, 0, 0, DMAP_MUTABLE) /*10 = /dev/c2 */
DT(0, 0, 0, 0, DMAP_MUTABLE) /*11 = not used */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*12 = /dev/c3 */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*13 = /dev/audio */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*14 = /dev/mixer */
DT(1, gen_opcl, gen_io, LOG_PROC_NR, 0) /*15 = /dev/klog */
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*16 = /dev/random*/
DT(0, no_dev, 0, NONE, DMAP_MUTABLE) /*17 = /dev/cmos */
#endif /* IBM_PC */
};
/*===========================================================================*
* do_devctl *
*===========================================================================*/
PUBLIC int do_devctl()
{
if (!super_user)
{
printf("FS: unauthorized call of do_devctl by proc %d\n",
who_e);
return(EPERM); /* only su (should be only RS or some drivers)
* may call do_devctl.
*/
}
return fs_devctl(m_in.ctl_req, m_in.dev_nr, m_in.driver_nr,
m_in.dev_style, m_in.m_force);
}
/*===========================================================================*
* fs_devctl *
*===========================================================================*/
PUBLIC int fs_devctl(req, dev, proc_nr_e, style, force)
int req;
int dev;
int proc_nr_e;
int style;
int force;
{
int result, proc_nr_n;
switch(req) {
case DEV_MAP:
if (!force)
{
/* Check process number of new driver. */
if (isokendpt(proc_nr_e, &proc_nr_n) != OK)
return(EINVAL);
}
/* Try to update device mapping. */
result = map_driver(dev, proc_nr_e, style, force);
if (result == OK)
{
/* If a driver has completed its exec(), it can be announced to be
* up.
*/
if(force || fproc[proc_nr_n].fp_execced) {
dev_up(dev);
} else {
dmap[dev].dmap_flags |= DMAP_BABY;
}
}
break;
case DEV_UNMAP:
result = map_driver(dev, NONE, 0, 0);
break;
default:
result = EINVAL;
}
return(result);
}
/*===========================================================================*
* map_driver *
*===========================================================================*/
PUBLIC int map_driver(major, proc_nr_e, style, force)
int major; /* major number of the device */
int proc_nr_e; /* process number of the driver */
int style; /* style of the device */
int force;
{
/* Set a new device driver mapping in the dmap table. Given that correct
* arguments are given, this only works if the entry is mutable and the
* current driver is not busy. If the proc_nr is set to NONE, we're supposed
* to unmap it.
*
* Normal error codes are returned so that this function can be used from
* a system call that tries to dynamically install a new driver.
*/
struct dmap *dp;
int proc_nr_n;
/* Get pointer to device entry in the dmap table. */
if (major < 0 || major >= NR_DEVICES) return(ENODEV);
dp = &dmap[major];
/* Check if we're supposed to unmap it. If so, do it even
* if busy or unmutable, as unmap is called when driver has
* exited.
*/
if(proc_nr_e == NONE) {
dp->dmap_opcl = no_dev;
dp->dmap_io = no_dev_io;
dp->dmap_driver = NONE;
dp->dmap_flags = DMAP_MUTABLE; /* When gone, not busy or reserved. */
return(OK);
}
/* See if updating the entry is allowed. */
if (! (dp->dmap_flags & DMAP_MUTABLE)) return(EPERM);
if (dp->dmap_flags & DMAP_BUSY) return(EBUSY);
if (!force)
{
/* Check process number of new driver. */
if (isokendpt(proc_nr_e, &proc_nr_n) != OK)
return(EINVAL);
}
/* Try to update the entry. */
switch (style) {
case STYLE_DEV: dp->dmap_opcl = gen_opcl; break;
case STYLE_TTY: dp->dmap_opcl = tty_opcl; break;
case STYLE_CLONE: dp->dmap_opcl = clone_opcl; break;
default: return(EINVAL);
}
dp->dmap_io = gen_io;
dp->dmap_driver = proc_nr_e;
return(OK);
}
/*===========================================================================*
* dmap_unmap_by_endpt *
*===========================================================================*/
PUBLIC void dmap_unmap_by_endpt(int proc_nr_e)
{
int i, r;
for (i=0; i<NR_DEVICES; i++)
if(dmap[i].dmap_driver && dmap[i].dmap_driver == proc_nr_e)
if((r=map_driver(i, NONE, 0, 0)) != OK)
printf("FS: unmap of p %d / d %d failed: %d\n", proc_nr_e,i,r);
return;
}
/*===========================================================================*
* build_dmap *
*===========================================================================*/
PUBLIC void build_dmap()
{
/* Initialize the table with all device <-> driver mappings. Then, map
* the boot driver to a controller and update the dmap table to that
* selection. The boot driver and the controller it handles are set at
* the boot monitor.
*/
int i;
struct dmap *dp;
/* Build table with device <-> driver mappings. */
for (i=0; i<NR_DEVICES; i++) {
dp = &dmap[i];
if (i < sizeof(init_dmap)/sizeof(struct dmap) &&
init_dmap[i].dmap_opcl != no_dev) { /* a preset driver */
dp->dmap_opcl = init_dmap[i].dmap_opcl;
dp->dmap_io = init_dmap[i].dmap_io;
dp->dmap_driver = init_dmap[i].dmap_driver;
dp->dmap_flags = init_dmap[i].dmap_flags;
} else { /* no default */
dp->dmap_opcl = no_dev;
dp->dmap_io = no_dev_io;
dp->dmap_driver = NONE;
dp->dmap_flags = DMAP_MUTABLE;
}
}
#if 0
/* Get settings of 'controller' and 'driver' at the boot monitor. */
if ((s = env_get_param("label", driver, sizeof(driver))) != OK)
panic(__FILE__,"couldn't get boot monitor parameter 'driver'", s);
if ((s = env_get_param("controller", controller, sizeof(controller))) != OK)
panic(__FILE__,"couldn't get boot monitor parameter 'controller'", s);
/* Determine major number to map driver onto. */
if (controller[0] == 'f' && controller[1] == 'd') {
major = FLOPPY_MAJOR;
}
else if (controller[0] == 'c' && isdigit(controller[1])) {
if ((nr = (unsigned) atoi(&controller[1])) > NR_CTRLRS)
panic(__FILE__,"monitor 'controller' maximum 'c#' is", NR_CTRLRS);
major = CTRLR(nr);
}
else {
panic(__FILE__,"monitor 'controller' syntax is 'c#' of 'fd'", NO_NUM);
}
/* Now try to set the actual mapping and report to the user. */
if ((s=map_driver(major, DRVR_PROC_NR, STYLE_DEV)) != OK)
panic(__FILE__,"map_driver failed",s);
printf("Boot medium driver: %s driver mapped onto controller %s.\n",
driver, controller);
#endif
}
/*===========================================================================*
* dmap_driver_match *
*===========================================================================*/
PUBLIC int dmap_driver_match(int proc, int major)
{
if (major < 0 || major >= NR_DEVICES) return(0);
if(dmap[major].dmap_driver != NONE && dmap[major].dmap_driver == proc)
return 1;
return 0;
}
/*===========================================================================*
* dmap_endpt_up *
*===========================================================================*/
PUBLIC void dmap_endpt_up(int proc_e)
{
int i;
for (i=0; i<NR_DEVICES; i++) {
if(dmap[i].dmap_driver != NONE
&& dmap[i].dmap_driver == proc_e
&& (dmap[i].dmap_flags & DMAP_BABY)) {
dmap[i].dmap_flags &= ~DMAP_BABY;
dev_up(i);
}
}
return;
}