Commit d78b462d authored by Jeff Dike's avatar Jeff Dike

Merge http://jdike.stearns.org:5000/mconfig-2.5

into uml.karaya.com:/home/jdike/linux/2.5/uml-2.5
parents 625207a1 8631e9b3
...@@ -24,7 +24,8 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts) ...@@ -24,7 +24,8 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
return(NULL); return(NULL);
} }
static int not_configged_open(int input, int output, int primary, void *data) static int not_configged_open(int input, int output, int primary, void *data,
char **dev_out)
{ {
printk(KERN_ERR "Using a channel type which is configured out of " printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n"); "UML\n");
...@@ -112,7 +113,8 @@ static int open_one_chan(struct chan *chan, int input, int output, int primary) ...@@ -112,7 +113,8 @@ static int open_one_chan(struct chan *chan, int input, int output, int primary)
if(chan->opened) return(0); if(chan->opened) return(0);
if(chan->ops->open == NULL) fd = 0; if(chan->ops->open == NULL) fd = 0;
else fd = (*chan->ops->open)(input, output, primary, chan->data); else fd = (*chan->ops->open)(input, output, primary, chan->data,
&chan->dev);
if(fd < 0) return(fd); if(fd < 0) return(fd);
chan->fd = fd; chan->fd = fd;
...@@ -258,6 +260,66 @@ void free_chan(struct list_head *chans) ...@@ -258,6 +260,66 @@ void free_chan(struct list_head *chans)
} }
} }
static int one_chan_config_string(struct chan *chan, char *str, int size,
char **error_out)
{
int n = 0;
CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
if(chan->dev == NULL){
CONFIG_CHUNK(str, size, n, "", 1);
return(n);
}
CONFIG_CHUNK(str, size, n, ":", 0);
CONFIG_CHUNK(str, size, n, chan->dev, 0);
return(n);
}
static int chan_pair_config_string(struct chan *in, struct chan *out,
char *str, int size, char **error_out)
{
int n;
n = one_chan_config_string(in, str, size, error_out);
str += n;
size -= n;
if(in == out){
CONFIG_CHUNK(str, size, n, "", 1);
return(n);
}
CONFIG_CHUNK(str, size, n, ",", 1);
n = one_chan_config_string(out, str, size, error_out);
str += n;
size -= n;
CONFIG_CHUNK(str, size, n, "", 1);
return(n);
}
int chan_config_string(struct list_head *chans, char *str, int size,
char **error_out)
{
struct list_head *ele;
struct chan *chan, *in = NULL, *out = NULL;
list_for_each(ele, chans){
chan = list_entry(ele, struct chan, list);
if(!chan->primary)
continue;
if(chan->input)
in = chan;
if(chan->output)
out = chan;
}
return(chan_pair_config_string(in, out, str, size, error_out));
}
struct chan_type { struct chan_type {
char *key; char *key;
struct chan_ops *ops; struct chan_ops *ops;
......
...@@ -15,6 +15,7 @@ struct fd_chan { ...@@ -15,6 +15,7 @@ struct fd_chan {
int fd; int fd;
int raw; int raw;
struct termios tt; struct termios tt;
char str[sizeof("1234567890\0")];
}; };
void *fd_init(char *str, int device, struct chan_opts *opts) void *fd_init(char *str, int device, struct chan_opts *opts)
...@@ -40,7 +41,7 @@ void *fd_init(char *str, int device, struct chan_opts *opts) ...@@ -40,7 +41,7 @@ void *fd_init(char *str, int device, struct chan_opts *opts)
return(data); return(data);
} }
int fd_open(int input, int output, int primary, void *d) int fd_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct fd_chan *data = d; struct fd_chan *data = d;
...@@ -48,6 +49,8 @@ int fd_open(int input, int output, int primary, void *d) ...@@ -48,6 +49,8 @@ int fd_open(int input, int output, int primary, void *d)
tcgetattr(data->fd, &data->tt); tcgetattr(data->fd, &data->tt);
raw(data->fd, 0); raw(data->fd, 0);
} }
sprintf(data->str, "%d", data->fd);
*dev_out = data->str;
return(data->fd); return(data->fd);
} }
...@@ -69,6 +72,7 @@ int fd_console_write(int fd, const char *buf, int n, void *d) ...@@ -69,6 +72,7 @@ int fd_console_write(int fd, const char *buf, int n, void *d)
} }
struct chan_ops fd_ops = { struct chan_ops fd_ops = {
type: "fd",
init: fd_init, init: fd_init,
open: fd_open, open: fd_open,
close: fd_close, close: fd_close,
......
...@@ -8,11 +8,13 @@ ...@@ -8,11 +8,13 @@
#include "linux/list.h" #include "linux/list.h"
#include "linux/devfs_fs_kernel.h" #include "linux/devfs_fs_kernel.h"
#include "asm/irq.h" #include "asm/irq.h"
#include "asm/uaccess.h"
#include "chan_kern.h" #include "chan_kern.h"
#include "irq_user.h" #include "irq_user.h"
#include "line.h" #include "line.h"
#include "kern.h" #include "kern.h"
#include "user_util.h" #include "user_util.h"
#include "kern_util.h"
#include "os.h" #include "os.h"
#define LINE_BUFSIZE 4096 #define LINE_BUFSIZE 4096
...@@ -281,7 +283,7 @@ void close_lines(struct line *lines, int nlines) ...@@ -281,7 +283,7 @@ void close_lines(struct line *lines, int nlines)
close_chan(&lines[i].chan_list); close_chan(&lines[i].chan_list);
} }
void line_setup(struct line *lines, int num, char *init) int line_setup(struct line *lines, int num, char *init, int all_allowed)
{ {
int i, n; int i, n;
char *end; char *end;
...@@ -292,12 +294,36 @@ void line_setup(struct line *lines, int num, char *init) ...@@ -292,12 +294,36 @@ void line_setup(struct line *lines, int num, char *init)
if(*end != '='){ if(*end != '='){
printk(KERN_ERR "line_setup failed to parse \"%s\"\n", printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
init); init);
return; return(1);
} }
init = end; init = end;
} }
init++; init++;
if(n == -1){ if((n >= 0) && (n >= num)){
printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
n, num);
return(1);
}
else if(n >= 0){
if(lines[n].count > 0){
printk("line_setup - device %d is open\n", n);
return(1);
}
if(lines[n].init_pri <= INIT_ONE){
lines[n].init_pri = INIT_ONE;
if(!strcmp(init, "none")) lines[n].valid = 0;
else {
lines[n].init_str = init;
lines[n].valid = 1;
}
}
}
else if(!all_allowed){
printk("line_setup - can't configure all devices from "
"mconsole\n");
return(1);
}
else {
for(i = 0; i < num; i++){ for(i = 0; i < num; i++){
if(lines[i].init_pri <= INIT_ALL){ if(lines[i].init_pri <= INIT_ALL){
lines[i].init_pri = INIT_ALL; lines[i].init_pri = INIT_ALL;
...@@ -309,14 +335,57 @@ void line_setup(struct line *lines, int num, char *init) ...@@ -309,14 +335,57 @@ void line_setup(struct line *lines, int num, char *init)
} }
} }
} }
else if(lines[n].init_pri <= INIT_ONE){ return(0);
lines[n].init_pri = INIT_ONE; }
if(!strcmp(init, "none")) lines[n].valid = 0;
else { int line_config(struct line *lines, int num, char *str)
lines[n].init_str = init; {
lines[n].valid = 1; char *new = uml_strdup(str);
}
if(new == NULL){
printk("line_config - uml_strdup failed\n");
return(-ENOMEM);
}
return(line_setup(lines, num, new, 0));
}
int line_get_config(char *name, struct line *lines, int num, char *str,
int size, char **error_out)
{
struct line *line;
char *end;
int dev, n = 0;
dev = simple_strtoul(name, &end, 0);
if((*end != '\0') || (end == name)){
*error_out = "line_setup failed to parse device number";
return(0);
} }
if((dev < 0) || (dev >= num)){
*error_out = "device number of of range";
return(0);
}
line = &lines[dev];
down(&line->sem);
if(!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
else if(line->count == 0)
CONFIG_CHUNK(str, size, n, line->init_str, 1);
else n = chan_config_string(&line->chan_list, str, size, error_out);
up(&line->sem);
return(n);
}
int line_remove(struct line *lines, int num, char *str)
{
char config[sizeof("conxxxx=none\0")];
sprintf(config, "%s=none", str);
return(line_setup(lines, num, config, 0));
} }
void line_register_devfs(struct lines *set, struct line_driver *line_driver, void line_register_devfs(struct lines *set, struct line_driver *line_driver,
...@@ -366,6 +435,8 @@ void line_register_devfs(struct lines *set, struct line_driver *line_driver, ...@@ -366,6 +435,8 @@ void line_register_devfs(struct lines *set, struct line_driver *line_driver,
if(!lines[i].valid) if(!lines[i].valid)
tty_unregister_devfs(driver, driver->minor_start + i); tty_unregister_devfs(driver, driver->minor_start + i);
} }
mconsole_register_dev(&line_driver->mc);
} }
void lines_init(struct line *lines, int nlines) void lines_init(struct line *lines, int nlines)
......
...@@ -108,6 +108,7 @@ void mconsole_version(struct mc_request *req) ...@@ -108,6 +108,7 @@ void mconsole_version(struct mc_request *req)
reboot - Reboot UML reboot - Reboot UML
config <dev>=<config> - Add a new device to UML; config <dev>=<config> - Add a new device to UML;
same syntax as command line same syntax as command line
config <dev> - Query the configuration of a device
remove <dev> - Remove a device from UML remove <dev> - Remove a device from UML
sysrq <letter> - Performs the SysRq action controlled by the letter sysrq <letter> - Performs the SysRq action controlled by the letter
cad - invoke the Ctl-Alt-Del handler cad - invoke the Ctl-Alt-Del handler
...@@ -181,10 +182,56 @@ static struct mc_device *mconsole_find_dev(char *name) ...@@ -181,10 +182,56 @@ static struct mc_device *mconsole_find_dev(char *name)
return(NULL); return(NULL);
} }
#define CONFIG_BUF_SIZE 64
static void mconsole_get_config(int (*get_config)(char *, char *, int,
char **),
struct mc_request *req, char *name)
{
char default_buf[CONFIG_BUF_SIZE], *error, *buf;
int n, size;
if(get_config == NULL){
mconsole_reply(req, "No get_config routine defined", 1, 0);
return;
}
error = NULL;
size = sizeof(default_buf)/sizeof(default_buf[0]);
buf = default_buf;
while(1){
n = (*get_config)(name, buf, size, &error);
if(error != NULL){
mconsole_reply(req, error, 1, 0);
goto out;
}
if(n <= size){
mconsole_reply(req, buf, 0, 0);
goto out;
}
if(buf != default_buf)
kfree(buf);
size = n;
buf = kmalloc(size, GFP_KERNEL);
if(buf == NULL){
mconsole_reply(req, "Failed to allocate buffer", 1, 0);
return;
}
}
out:
if(buf != default_buf)
kfree(buf);
}
void mconsole_config(struct mc_request *req) void mconsole_config(struct mc_request *req)
{ {
struct mc_device *dev; struct mc_device *dev;
char *ptr = req->request.data; char *ptr = req->request.data, *name;
int err; int err;
ptr += strlen("config"); ptr += strlen("config");
...@@ -194,8 +241,17 @@ void mconsole_config(struct mc_request *req) ...@@ -194,8 +241,17 @@ void mconsole_config(struct mc_request *req)
mconsole_reply(req, "Bad configuration option", 1, 0); mconsole_reply(req, "Bad configuration option", 1, 0);
return; return;
} }
err = (*dev->config)(&ptr[strlen(dev->name)]);
mconsole_reply(req, "", err, 0); name = &ptr[strlen(dev->name)];
ptr = name;
while((*ptr != '=') && (*ptr != '\0'))
ptr++;
if(*ptr == '='){
err = (*dev->config)(name);
mconsole_reply(req, "", err, 0);
}
else mconsole_get_config(dev->get_config, req, name);
} }
void mconsole_remove(struct mc_request *req) void mconsole_remove(struct mc_request *req)
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Licensed under the GPL * Licensed under the GPL
*/ */
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include "chan_user.h" #include "chan_user.h"
...@@ -15,8 +16,9 @@ void *null_init(char *str, int device, struct chan_opts *opts) ...@@ -15,8 +16,9 @@ void *null_init(char *str, int device, struct chan_opts *opts)
return(&null_chan); return(&null_chan);
} }
int null_open(int input, int output, int primary, void *d) int null_open(int input, int output, int primary, void *d, char **dev_out)
{ {
*dev_out = NULL;
return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0)); return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0));
} }
...@@ -30,6 +32,7 @@ void null_free(void *data) ...@@ -30,6 +32,7 @@ void null_free(void *data)
} }
struct chan_ops null_ops = { struct chan_ops null_ops = {
type: "null",
init: null_init, init: null_init,
open: null_open, open: null_open,
close: generic_close, close: generic_close,
......
...@@ -3,11 +3,12 @@ ...@@ -3,11 +3,12 @@
* Licensed under the GPL * Licensed under the GPL
*/ */
#include <stdio.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <termios.h> #include <termios.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
...@@ -24,6 +25,7 @@ struct port_chan { ...@@ -24,6 +25,7 @@ struct port_chan {
int raw; int raw;
struct termios tt; struct termios tt;
void *kernel_data; void *kernel_data;
char dev[sizeof("32768\0")];
}; };
void *port_init(char *str, int device, struct chan_opts *opts) void *port_init(char *str, int device, struct chan_opts *opts)
...@@ -50,11 +52,12 @@ void *port_init(char *str, int device, struct chan_opts *opts) ...@@ -50,11 +52,12 @@ void *port_init(char *str, int device, struct chan_opts *opts)
if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL); if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
*data = ((struct port_chan) { raw : opts->raw, *data = ((struct port_chan) { raw : opts->raw,
kernel_data : kern_data }); kernel_data : kern_data });
sprintf(data->dev, "%d", port);
return(data); return(data);
} }
int port_open(int input, int output, int primary, void *d) int port_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct port_chan *data = d; struct port_chan *data = d;
int fd; int fd;
...@@ -64,6 +67,7 @@ int port_open(int input, int output, int primary, void *d) ...@@ -64,6 +67,7 @@ int port_open(int input, int output, int primary, void *d)
tcgetattr(fd, &data->tt); tcgetattr(fd, &data->tt);
raw(fd, 0); raw(fd, 0);
} }
*dev_out = data->dev;
return(fd); return(fd);
} }
...@@ -91,6 +95,7 @@ void port_free(void *d) ...@@ -91,6 +95,7 @@ void port_free(void *d)
} }
struct chan_ops port_ops = { struct chan_ops port_ops = {
type: "port",
init: port_init, init: port_init,
open: port_open, open: port_open,
close: port_close, close: port_close,
......
...@@ -19,6 +19,7 @@ struct pty_chan { ...@@ -19,6 +19,7 @@ struct pty_chan {
int dev; int dev;
int raw; int raw;
struct termios tt; struct termios tt;
char dev_name[sizeof("/dev/pts/0123456\0")];
}; };
void *pty_chan_init(char *str, int device, struct chan_opts *opts) void *pty_chan_init(char *str, int device, struct chan_opts *opts)
...@@ -32,9 +33,10 @@ void *pty_chan_init(char *str, int device, struct chan_opts *opts) ...@@ -32,9 +33,10 @@ void *pty_chan_init(char *str, int device, struct chan_opts *opts)
return(data); return(data);
} }
int pts_open(int input, int output, int primary, void *d) int pts_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct pty_chan *data = d; struct pty_chan *data = d;
char *dev;
int fd; int fd;
if((fd = get_pty()) < 0){ if((fd = get_pty()) < 0){
...@@ -45,7 +47,11 @@ int pts_open(int input, int output, int primary, void *d) ...@@ -45,7 +47,11 @@ int pts_open(int input, int output, int primary, void *d)
tcgetattr(fd, &data->tt); tcgetattr(fd, &data->tt);
raw(fd, 0); raw(fd, 0);
} }
if(data->announce) (*data->announce)(ptsname(fd), data->dev);
dev = ptsname(fd);
sprintf(data->dev_name, "%s", dev);
*dev_out = data->dev_name;
if(data->announce) (*data->announce)(dev, data->dev);
return(fd); return(fd);
} }
...@@ -94,7 +100,7 @@ static void grantpt_cb(void *arg) ...@@ -94,7 +100,7 @@ static void grantpt_cb(void *arg)
info->err = errno; info->err = errno;
} }
int pty_open(int input, int output, int primary, void *d) int pty_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct pty_chan *data = d; struct pty_chan *data = d;
int fd; int fd;
...@@ -110,6 +116,9 @@ int pty_open(int input, int output, int primary, void *d) ...@@ -110,6 +116,9 @@ int pty_open(int input, int output, int primary, void *d)
if(data->raw) raw(fd, 0); if(data->raw) raw(fd, 0);
if(data->announce) (*data->announce)(dev, data->dev); if(data->announce) (*data->announce)(dev, data->dev);
sprintf(data->dev_name, "%s", dev);
*dev_out = data->dev_name;
return(fd); return(fd);
} }
...@@ -121,6 +130,7 @@ int pty_console_write(int fd, const char *buf, int n, void *d) ...@@ -121,6 +130,7 @@ int pty_console_write(int fd, const char *buf, int n, void *d)
} }
struct chan_ops pty_ops = { struct chan_ops pty_ops = {
type: "pty",
init: pty_chan_init, init: pty_chan_init,
open: pty_open, open: pty_open,
close: generic_close, close: generic_close,
...@@ -133,6 +143,7 @@ struct chan_ops pty_ops = { ...@@ -133,6 +143,7 @@ struct chan_ops pty_ops = {
}; };
struct chan_ops pts_ops = { struct chan_ops pts_ops = {
type: "pts",
init: pty_chan_init, init: pty_chan_init,
open: pts_open, open: pts_open,
close: generic_close, close: generic_close,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "kern.h" #include "kern.h"
#include "init.h" #include "init.h"
#include "irq_user.h" #include "irq_user.h"
#include "mconsole_kern.h"
#include "2_5compat.h" #include "2_5compat.h"
static int ssl_version = 1; static int ssl_version = 1;
...@@ -47,6 +48,10 @@ static struct chan_opts opts = { ...@@ -47,6 +48,10 @@ static struct chan_opts opts = {
in_kernel : 1, in_kernel : 1,
}; };
static int ssl_config(char *str);
static int ssl_get_config(char *dev, char *str, int size, char **error_out);
static int ssl_remove(char *str);
static struct line_driver driver = { static struct line_driver driver = {
name : "UML serial line", name : "UML serial line",
devfs_name : "tts/%d", devfs_name : "tts/%d",
...@@ -60,6 +65,12 @@ static struct line_driver driver = { ...@@ -60,6 +65,12 @@ static struct line_driver driver = {
write_irq_name : "ssl-write", write_irq_name : "ssl-write",
symlink_from : "serial", symlink_from : "serial",
symlink_to : "tts", symlink_to : "tts",
mc : {
name : "ssl",
config : ssl_config,
get_config : ssl_get_config,
remove : ssl_remove,
},
}; };
/* The array is initialized by line_init, which is an initcall. The /* The array is initialized by line_init, which is an initcall. The
...@@ -70,6 +81,25 @@ static struct line serial_lines[NR_PORTS] = ...@@ -70,6 +81,25 @@ static struct line serial_lines[NR_PORTS] =
static struct lines lines = LINES_INIT(NR_PORTS); static struct lines lines = LINES_INIT(NR_PORTS);
static int ssl_config(char *str)
{
return(line_config(serial_lines,
sizeof(serial_lines)/sizeof(serial_lines[0]), str));
}
static int ssl_get_config(char *dev, char *str, int size, char **error_out)
{
return(line_get_config(dev, serial_lines,
sizeof(serial_lines)/sizeof(serial_lines[0]),
str, size, error_out));
}
static int ssl_remove(char *str)
{
return(line_remove(serial_lines,
sizeof(serial_lines)/sizeof(serial_lines[0]), str));
}
int ssl_open(struct tty_struct *tty, struct file *filp) int ssl_open(struct tty_struct *tty, struct file *filp)
{ {
return(line_open(serial_lines, tty, &opts)); return(line_open(serial_lines, tty, &opts));
...@@ -207,7 +237,7 @@ __initcall(ssl_init); ...@@ -207,7 +237,7 @@ __initcall(ssl_init);
static int ssl_chan_setup(char *str) static int ssl_chan_setup(char *str)
{ {
line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]), line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]),
str); str, 1);
return(1); return(1);
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "user_util.h" #include "user_util.h"
#include "kern_util.h" #include "kern_util.h"
#include "irq_user.h" #include "irq_user.h"
#include "mconsole_kern.h"
#include "init.h" #include "init.h"
#include "2_5compat.h" #include "2_5compat.h"
...@@ -41,6 +42,7 @@ static struct tty_driver console_driver; ...@@ -41,6 +42,7 @@ static struct tty_driver console_driver;
static int console_refcount = 0; static int console_refcount = 0;
static struct chan_ops init_console_ops = { static struct chan_ops init_console_ops = {
type: "you shouldn't see this",
init : NULL, init : NULL,
open : NULL, open : NULL,
close : NULL, close : NULL,
...@@ -78,6 +80,10 @@ static struct chan_opts opts = { ...@@ -78,6 +80,10 @@ static struct chan_opts opts = {
in_kernel : 1, in_kernel : 1,
}; };
static int con_config(char *str);
static int con_get_config(char *dev, char *str, int size, char **error_out);
static int con_remove(char *str);
static struct line_driver driver = { static struct line_driver driver = {
name : "UML console", name : "UML console",
devfs_name : "vc/%d", devfs_name : "vc/%d",
...@@ -91,6 +97,12 @@ static struct line_driver driver = { ...@@ -91,6 +97,12 @@ static struct line_driver driver = {
write_irq_name : "console-write", write_irq_name : "console-write",
symlink_from : "ttys", symlink_from : "ttys",
symlink_to : "vc", symlink_to : "vc",
mc : {
name : "con",
config : con_config,
get_config : con_get_config,
remove : con_remove,
},
}; };
static struct lines console_lines = LINES_INIT(MAX_TTYS); static struct lines console_lines = LINES_INIT(MAX_TTYS);
...@@ -102,6 +114,22 @@ struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), ...@@ -102,6 +114,22 @@ struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
[ 1 ... MAX_TTYS - 1 ] = [ 1 ... MAX_TTYS - 1 ] =
LINE_INIT(CONFIG_CON_CHAN, &driver) }; LINE_INIT(CONFIG_CON_CHAN, &driver) };
static int con_config(char *str)
{
return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str));
}
static int con_get_config(char *dev, char *str, int size, char **error_out)
{
return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str,
size, error_out));
}
static int con_remove(char *str)
{
return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str));
}
static int open_console(struct tty_struct *tty) static int open_console(struct tty_struct *tty)
{ {
return(line_open(vts, tty, &opts)); return(line_open(vts, tty, &opts));
...@@ -195,7 +223,7 @@ void stdio_console_init(void) ...@@ -195,7 +223,7 @@ void stdio_console_init(void)
static int console_chan_setup(char *str) static int console_chan_setup(char *str)
{ {
line_setup(vts, sizeof(vts)/sizeof(vts[0]), str); line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1);
return(1); return(1);
} }
......
...@@ -30,14 +30,15 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts) ...@@ -30,14 +30,15 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts)
} }
str++; str++;
if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL); if((data = um_kmalloc(sizeof(*data))) == NULL)
return(NULL);
*data = ((struct tty_chan) { dev : str, *data = ((struct tty_chan) { dev : str,
raw : opts->raw }); raw : opts->raw });
return(data); return(data);
} }
int tty_open(int input, int output, int primary, void *d) int tty_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct tty_chan *data = d; struct tty_chan *data = d;
int fd; int fd;
...@@ -48,6 +49,8 @@ int tty_open(int input, int output, int primary, void *d) ...@@ -48,6 +49,8 @@ int tty_open(int input, int output, int primary, void *d)
tcgetattr(fd, &data->tt); tcgetattr(fd, &data->tt);
raw(fd, 0); raw(fd, 0);
} }
*dev_out = data->dev;
return(fd); return(fd);
} }
...@@ -59,6 +62,7 @@ int tty_console_write(int fd, const char *buf, int n, void *d) ...@@ -59,6 +62,7 @@ int tty_console_write(int fd, const char *buf, int n, void *d)
} }
struct chan_ops tty_ops = { struct chan_ops tty_ops = {
type: "tty",
init: tty_chan_init, init: tty_chan_init,
open: tty_open, open: tty_open,
close: generic_close, close: generic_close,
......
...@@ -577,6 +577,44 @@ static int ubd_config(char *str) ...@@ -577,6 +577,44 @@ static int ubd_config(char *str)
return(err); return(err);
} }
static int ubd_get_config(char *dev, char *str, int size, char **error_out)
{
struct ubd *ubd;
char *end;
int major, n = 0;
major = simple_strtoul(dev, &end, 0);
if((*end != '\0') || (end == dev)){
*error_out = "ubd_get_config : didn't parse major number";
return(-1);
}
if((major >= MAX_DEV) || (major < 0)){
*error_out = "ubd_get_config : major number out of range";
return(-1);
}
ubd = &ubd_dev[major];
spin_lock(&ubd_lock);
if(ubd->file == NULL){
CONFIG_CHUNK(str, size, n, "", 1);
goto out;
}
CONFIG_CHUNK(str, size, n, ubd->file, 0);
if(ubd->cow.file != NULL){
CONFIG_CHUNK(str, size, n, ",", 0);
CONFIG_CHUNK(str, size, n, ubd->cow.file, 1);
}
else CONFIG_CHUNK(str, size, n, "", 1);
out:
spin_unlock(&ubd_lock);
return(n);
}
static int ubd_remove(char *str) static int ubd_remove(char *str)
{ {
struct ubd *dev; struct ubd *dev;
...@@ -623,6 +661,7 @@ static int ubd_remove(char *str) ...@@ -623,6 +661,7 @@ static int ubd_remove(char *str)
static struct mc_device ubd_mc = { static struct mc_device ubd_mc = {
.name = "ubd", .name = "ubd",
.config = ubd_config, .config = ubd_config,
.get_config = ubd_get_config,
.remove = ubd_remove, .remove = ubd_remove,
}; };
......
...@@ -83,7 +83,7 @@ __uml_setup("xterm=", xterm_setup, ...@@ -83,7 +83,7 @@ __uml_setup("xterm=", xterm_setup,
" are 'xterm=gnome-terminal,-t,-x'.\n\n" " are 'xterm=gnome-terminal,-t,-x'.\n\n"
); );
int xterm_open(int input, int output, int primary, void *d) int xterm_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct xterm_chan *data = d; struct xterm_chan *data = d;
unsigned long stack; unsigned long stack;
...@@ -144,6 +144,7 @@ int xterm_open(int input, int output, int primary, void *d) ...@@ -144,6 +144,7 @@ int xterm_open(int input, int output, int primary, void *d)
if(data->raw) raw(new, 0); if(data->raw) raw(new, 0);
data->pid = pid; data->pid = pid;
*dev_out = NULL;
return(new); return(new);
} }
...@@ -171,6 +172,7 @@ int xterm_console_write(int fd, const char *buf, int n, void *d) ...@@ -171,6 +172,7 @@ int xterm_console_write(int fd, const char *buf, int n, void *d)
} }
struct chan_ops xterm_ops = { struct chan_ops xterm_ops = {
type: "xterm",
init: xterm_init, init: xterm_init,
open: xterm_open, open: xterm_open,
close: xterm_close, close: xterm_close,
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
struct chan { struct chan {
struct list_head list; struct list_head list;
char *dev;
unsigned int primary:1; unsigned int primary:1;
unsigned int input:1; unsigned int input:1;
unsigned int output:1; unsigned int output:1;
...@@ -38,6 +39,8 @@ extern int chan_window_size(struct list_head *chans, ...@@ -38,6 +39,8 @@ extern int chan_window_size(struct list_head *chans,
unsigned short *rows_out, unsigned short *rows_out,
unsigned short *cols_out); unsigned short *cols_out);
extern int chan_out_fd(struct list_head *chans); extern int chan_out_fd(struct list_head *chans);
extern int chan_config_string(struct list_head *chans, char *str, int size,
char **error_out);
#endif #endif
......
...@@ -19,8 +19,9 @@ struct chan_opts { ...@@ -19,8 +19,9 @@ struct chan_opts {
enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
struct chan_ops { struct chan_ops {
char *type;
void *(*init)(char *, int, struct chan_opts *); void *(*init)(char *, int, struct chan_opts *);
int (*open)(int, int, int, void *); int (*open)(int, int, int, void *, char **);
void (*close)(int, void *); void (*close)(int, void *);
int (*read)(int, char *, void *); int (*read)(int, char *, void *);
int (*write)(int, const char *, int, void *); int (*write)(int, const char *, int, void *);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "linux/tty.h" #include "linux/tty.h"
#include "asm/semaphore.h" #include "asm/semaphore.h"
#include "chan_user.h" #include "chan_user.h"
#include "mconsole_kern.h"
struct line_driver { struct line_driver {
char *name; char *name;
...@@ -25,6 +26,7 @@ struct line_driver { ...@@ -25,6 +26,7 @@ struct line_driver {
char *write_irq_name; char *write_irq_name;
char *symlink_from; char *symlink_from;
char *symlink_to; char *symlink_to;
struct mc_device mc;
}; };
struct line { struct line {
...@@ -70,8 +72,9 @@ extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused); ...@@ -70,8 +72,9 @@ extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused);
extern void line_close(struct line *lines, struct tty_struct *tty); extern void line_close(struct line *lines, struct tty_struct *tty);
extern int line_open(struct line *lines, struct tty_struct *tty, extern int line_open(struct line *lines, struct tty_struct *tty,
struct chan_opts *opts); struct chan_opts *opts);
extern void line_setup(struct line *lines, int num, char *init); extern int line_setup(struct line *lines, int num, char *init,
extern int line_write(struct line *line, struct tty_struct *tty, int all_allowed);
extern int line_write(struct line *line, struct tty_struct *tty,
const char *buf, int len); const char *buf, int len);
extern int line_write_room(struct tty_struct *tty); extern int line_write_room(struct tty_struct *tty);
extern char *add_xterm_umid(char *base); extern char *add_xterm_umid(char *base);
...@@ -84,6 +87,10 @@ extern void line_register_devfs(struct lines *set, ...@@ -84,6 +87,10 @@ extern void line_register_devfs(struct lines *set,
int nlines); int nlines);
extern void lines_init(struct line *lines, int nlines); extern void lines_init(struct line *lines, int nlines);
extern void close_lines(struct line *lines, int nlines); extern void close_lines(struct line *lines, int nlines);
extern int line_config(struct line *lines, int num, char *str);
extern int line_remove(struct line *lines, int num, char *str);
extern int line_get_config(char *dev, struct line *lines, int num, char *str,
int size, char **error_out);
#endif #endif
......
/* /*
* Copyright (C) 2001 Jeff Dike (jdike@karaya.com) * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL * Licensed under the GPL
*/ */
...@@ -19,9 +19,23 @@ struct mc_device { ...@@ -19,9 +19,23 @@ struct mc_device {
struct list_head list; struct list_head list;
char *name; char *name;
int (*config)(char *); int (*config)(char *);
int (*get_config)(char *, char *, int, char **);
int (*remove)(char *); int (*remove)(char *);
}; };
#define CONFIG_CHUNK(str, size, current, chunk, end) \
do { \
current += strlen(chunk); \
if(current >= size) \
str = NULL; \
if(str != NULL){ \
strcpy(str, chunk); \
str += strlen(chunk); \
} \
if(end) \
current++; \
} while(0)
#ifdef CONFIG_MCONSOLE #ifdef CONFIG_MCONSOLE
extern void mconsole_register_dev(struct mc_device *new); extern void mconsole_register_dev(struct mc_device *new);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment