diff -Naur -X exclude-files ac_cur/arch/um/drivers/mconsole_kern.c ac/arch/um/drivers/mconsole_kern.c --- ac_cur/arch/um/drivers/mconsole_kern.c Sun Jul 15 21:26:31 2001 +++ ac/arch/um/drivers/mconsole_kern.c Sun Jul 15 22:03:32 2001 @@ -10,11 +10,13 @@ #include "linux/reboot.h" #include "linux/utsname.h" #include "linux/ctype.h" +#include "linux/interrupt.h" #include "asm/irq.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" #include "mconsole.h" +#include "mconsole_kern.h" extern int create_listening_socket(void); extern int get_request(int fd, struct mconsole_request *req); @@ -33,16 +35,45 @@ return(unlink_socket()); } +LIST_HEAD(mc_requests); + +void mc_tasklet(unsigned long unused) +{ + struct mconsole_entry *req; + unsigned long flags; + int done; + + do { + save_flags(flags); + req = list_entry(mc_requests.next, struct mconsole_entry, + list); + list_del(&req->list); + done = list_empty(&mc_requests); + handle_request(&req->request); + kfree(req); + restore_flags(flags); + } while(!done); +} + +DECLARE_TASKLET(mconsole_tasklet, mc_tasklet, 0); + void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int fd; + struct mconsole_entry *new; struct mconsole_request req; fd = (int) dev_id; while (get_request(fd, &req)) { - handle_request(&req); + new = kmalloc(sizeof(req), GFP_ATOMIC); + if(new == NULL) + mconsole_reply(&req, "ERR Out of memory"); + else { + new->request = req; + list_add(&new->list, &mc_requests); + } } - + tasklet_schedule(&mconsole_tasklet); reactivate_fd(fd); } @@ -58,72 +89,72 @@ void mconsole_halt(struct mconsole_request *req) { - static struct tq_struct halt = { - routine: (void (*)(void *))machine_halt, - }; - mconsole_reply(req, "OK"); - schedule_task(&halt); + machine_halt(); } void mconsole_reboot(struct mconsole_request *req) { - static struct tq_struct reboot = { - routine: (void (*)(void *))machine_restart, - }; - mconsole_reply(req, "OK"); - schedule_task(&reboot); + machine_restart(NULL); } -static struct config_command configs[] = { - { "gdb=", config_gdb }, -}; +LIST_HEAD(mconsole_devices); + +void mconsole_register_dev(struct mc_device *new) +{ + list_add(&new->list, &mconsole_devices); +} + +static struct mc_device *mconsole_find_dev(char *name) +{ + struct list_head *ele; + struct mc_device *dev; + + list_for_each(ele, &mconsole_devices){ + dev = list_entry(ele, struct mc_device, list); + if(!strncmp(name, dev->name, strlen(dev->name))) + return(dev); + } + return(NULL); +} void mconsole_config(struct mconsole_request *req) { - struct config_command *c; + struct mc_device *dev; char *ptr = req->buf, *ok; - int i, err; + int err; ptr += strlen("config"); while(isspace(*ptr)) ptr++; - for(i=0;i<sizeof(configs)/sizeof(configs[0]);i++){ - c = &configs[i]; - if(!strncmp(ptr, c->command, strlen(c->command))){ - err = c->handler(&ptr[strlen(c->command)]); - if(err) ok = "ERR"; - else ok = "OK"; - mconsole_reply(req, ok); - return; - } + dev = mconsole_find_dev(ptr); + if(dev == NULL){ + mconsole_reply(req, "ERR Bad configuration option"); + return; } - mconsole_reply(req, "ERR Bad configuration option"); + err = (*dev->config)(&ptr[strlen(dev->name)]); + if(err) ok = "ERR"; + else ok = "OK"; + mconsole_reply(req, ok); } -static struct remove_command removes[] = { - { "gdb", remove_gdb }, -}; - void mconsole_remove(struct mconsole_request *req) { - struct remove_command *r; + struct mc_device *dev; char *ptr = req->buf, *ok; - int i, err; + int err; ptr += strlen("remove"); while(isspace(*ptr)) ptr++; - for(i=0;i<sizeof(removes)/sizeof(removes[0]);i++){ - r = &removes[i]; - if(!strncmp(ptr, r->command, strlen(r->command))){ - err = r->handler(); - if(err) ok = "ERR"; - else ok = "OK"; - mconsole_reply(req, ok); - return; - } + dev = mconsole_find_dev(ptr); + if(dev == NULL){ + mconsole_reply(req, "ERR Bad remove option"); + return; } - mconsole_reply(req, "ERR Bad remove option"); + err = (*dev->remove)(&ptr[strlen(dev->name)]); + if(err) ok = "ERR"; + else ok = "OK"; + mconsole_reply(req, ok); } int mconsole_init(void) diff -Naur -X exclude-files ac_cur/arch/um/drivers/ubd.c ac/arch/um/drivers/ubd.c --- ac_cur/arch/um/drivers/ubd.c Sun Jul 15 21:30:40 2001 +++ ac/arch/um/drivers/ubd.c Sun Jul 15 22:03:32 2001 @@ -13,12 +13,15 @@ #include "linux/devfs_fs_kernel.h" #include "linux/cdrom.h" #include "linux/proc_fs.h" +#include "linux/ctype.h" +#include "linux/capability.h" #include "asm/segment.h" #include "asm/uaccess.h" #include "asm/irq.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" +#include "mconsole_kern.h" static int ubd_open(struct inode * inode, struct file * filp); static int ubd_release(struct inode * inode, struct file * file); @@ -76,7 +79,19 @@ #define OPEN_FLAGS O_RDWR #endif -struct { +#define DEFAULT_UBD { \ + file: NULL, \ + is_dir: 0, \ + count: 0, \ + fd: -1, \ + size: -1, \ + boot_openflags: OPEN_FLAGS, \ + openflags: OPEN_FLAGS, \ + real: NULL, \ + fake: NULL, \ +} + +struct ubd { char *file; int is_dir; int count; @@ -84,9 +99,22 @@ __u64 size; int boot_openflags; int openflags; -} ubd_dev[MAX_DEV] = { { "root_fs", 0, 0, -1, 0, OPEN_FLAGS, OPEN_FLAGS }, - [ 1 ... MAX_DEV - 1 ] = - { NULL, 0, 0, -1, -1, OPEN_FLAGS, OPEN_FLAGS } }; + devfs_handle_t real; + devfs_handle_t fake; +} ubd_dev[MAX_DEV] = { +{ + file: "root_fs", + is_dir: 0, + count: 0, + fd: -1, + size: 0, + boot_openflags: OPEN_FLAGS, + openflags: OPEN_FLAGS, + real: NULL, + fake: NULL, +}, +[ 1 ... MAX_DEV - 1 ] = DEFAULT_UBD +}; static struct hd_driveid ubd_id = { cyls: 0, @@ -148,11 +176,12 @@ __setup("fake_ide", fake_ide_setup); -static int ubd_setup(char *str) +static int ubd_setup_common(char *str, int *index_out, int copy_name) { int n; int sync, perm = O_RDWR; + if(index_out) *index_out = -1; n = *str++; if(n == '='){ char *end; @@ -181,6 +210,7 @@ printk("ubd_setup : index out of range\n"); return(1); } + if(index_out) *index_out = n; sync = ubd_dev[n].boot_openflags & O_SYNC; if (*str == 'r') { perm = O_RDONLY; @@ -194,11 +224,21 @@ printk("ubd_setup : Expected '='\n"); return(1); } - ubd_dev[n].file = str; + if(copy_name){ + ubd_dev[n].file = kmalloc(strlen(str) + 1, GFP_ATOMIC); + if(ubd_dev[n].file == NULL) return(0); + strcpy(ubd_dev[n].file, str); + } + else ubd_dev[n].file = str; ubd_dev[n].boot_openflags = perm | sync; return(1); } +static int ubd_setup(char *str) +{ + return(ubd_setup_common(str, NULL, 0)); +} + __setup("ubd", ubd_setup); static int fakehd(char *str) @@ -270,15 +310,80 @@ int sync = 0; +devfs_handle_t ubd_dir_handle; + +static int ubd_add(int n) +{ + char name[sizeof("nnnnnn\0")], dev_name[sizeof("ubd0x")]; + + if(ubd_dev[n].file == NULL) return(-1); + sprintf(name, "%d", n); + ubd_dev[n].real = devfs_register (ubd_dir_handle, name, + DEVFS_FL_DEFAULT, MAJOR_NR, n, + S_IFBLK | S_IRUSR | S_IWUSR | + S_IRGRP |S_IWGRP, + &ubd_blops, NULL); + if(fake_major != 0){ + ubd_dev[n].fake = devfs_register (ubd_dir_handle, name, + DEVFS_FL_DEFAULT, fake_major, + n, S_IFBLK | S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP, + &ubd_blops, NULL); + } + if(!strcmp(ubd_gendisk.major_name, "ubd")){ + sprintf(dev_name, "%s%d", ubd_gendisk.major_name, n); + } + else sprintf(dev_name, "%s%c", ubd_gendisk.major_name, + n + 'a'); + make_ide_entries(dev_name); + return(0); +} + +static int ubd_config(char *str) +{ + int n, err; + + err = ubd_setup_common(str, &n, 1); + if(err != 1) return(-1); + if(n != -1) ubd_add(n); + return(0); +} + +static int ubd_remove(char *str) +{ + int n; + + if(!isdigit(*str)) return(-1); + n = *str - '0'; + if(ubd_dev[n].file == NULL) return(0); + if(ubd_dev[n].count > 0) return(-1); + if(ubd_dev[n].real != NULL) devfs_unregister(ubd_dev[n].real); + if(ubd_dev[n].fake != NULL) devfs_unregister(ubd_dev[n].fake); + ubd_dev[n] = ((struct ubd) DEFAULT_UBD); + return(0); +} + +static struct mc_device ubd_mc = { + name: "ubd", + config: ubd_config, + remove: ubd_remove, +}; + +int ubd_mc_init(void) +{ + mconsole_register_dev(&ubd_mc); + return(0); +} + +__initcall(ubd_mc_init); + int ubd_init(void) { unsigned long stack; int i, err; - char name[6], dev_name[sizeof("ubd0x")]; - devfs_handle_t devfs_handle; request_queue_t *q; - devfs_handle = devfs_mk_dir (NULL, "ubd", NULL); + ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL); if (devfs_register_blkdev(MAJOR_NR, "ubd", &ubd_blops)) { printk("ubd: unable to get major %d\n", MAJOR_NR); return -1; @@ -304,28 +409,7 @@ fake_gendisk.next = gendisk_head; gendisk_head = &fake_gendisk; } - for(i=0;i<MAX_DEV;i++){ - if(ubd_dev[i].file == NULL) continue; - sprintf(name, "%d", i); - devfs_register (devfs_handle, name, DEVFS_FL_DEFAULT, - MAJOR_NR, i, - S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP, - &ubd_blops, NULL); - if(fake_major != 0){ - devfs_register (devfs_handle, name, - DEVFS_FL_DEFAULT, fake_major, i, - S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | - S_IWGRP, &ubd_blops, NULL); - } - if(!strcmp(ubd_gendisk.major_name, "ubd")){ - sprintf(dev_name, "%s%d", ubd_gendisk.major_name, i); - } - else { - sprintf(dev_name, "%s%c", ubd_gendisk.major_name, - i + 'a'); - } - make_ide_entries(dev_name); - } + for(i=0;i<MAX_DEV;i++) ubd_add(i); if(sync){ printk("ubd : Synchronous mode\n"); return(0); diff -Naur -X exclude-files ac_cur/arch/um/include/mconsole_kern.h ac/arch/um/include/mconsole_kern.h --- ac_cur/arch/um/include/mconsole_kern.h Wed Dec 31 19:00:00 1969 +++ ac/arch/um/include/mconsole_kern.h Sun Jul 15 22:03:32 2001 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MCONSOLE_KERN_H__ +#define __MCONSOLE_KERN_H__ + +#include "linux/list.h" +#include "mconsole.h" + +struct mconsole_entry { + struct list_head list; + struct mconsole_request request; +}; + +struct mc_device { + struct list_head list; + char *name; + int (*config)(char *); + int (*remove)(char *); +}; + +extern void mconsole_register_dev(struct mc_device *new); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/kernel/trap_kern.c ac/arch/um/kernel/trap_kern.c --- ac_cur/arch/um/kernel/trap_kern.c Sun Jul 15 21:26:31 2001 +++ ac/arch/um/kernel/trap_kern.c Sun Jul 15 22:03:32 2001 @@ -18,6 +18,7 @@ #include "kern.h" #include "chan.h" #include "debug.h" +#include "mconsole_kern.h" extern int nsyscalls; @@ -218,10 +219,11 @@ init_proxy(debugger_pid, 0, 0); } -int config_gdb(char *str) +int gdb_config(char *str) { struct gdb_data data; + if(*str++ != '=') return(-1); data.str = str; tracing_cb(config_gdb_cb, &data); return(data.err); @@ -232,11 +234,25 @@ exit_debugger_cb(NULL); } -int remove_gdb(void) +int gdb_remove(char *unused) { tracing_cb(remove_gdb_cb, NULL); return(0); } + +static struct mc_device gdb_mc = { + name: "gdb", + config: gdb_config, + remove: gdb_remove, +}; + +int gdb_mc_init(void) +{ + mconsole_register_dev(&gdb_mc); + return(0); +} + +__initcall(gdb_mc_init); void signal_usr1(int sig) {